├── extras └── logo │ └── logo.PNG ├── src ├── bin │ ├── typeCheck.js │ ├── postCreateLabel.js │ ├── postCreateIssues.js │ ├── getReleases.js │ ├── getContributors.js │ ├── getSearchIssues.js │ ├── getStargazers.js │ ├── getCommits.js │ ├── getAllPullRequests.js │ ├── getAllIssues.js │ ├── constants.js │ ├── weeklyDigest.js │ ├── manageAppInstallation.js │ └── initCreateWeeklyDigest.js └── markdown │ ├── getLongMonth.js │ ├── getDate.js │ ├── getNumDayFromLongDay.js │ ├── checkDuplicates.js │ ├── markdownReleases.js │ ├── markdownCommits.js │ ├── markdownStargazers.js │ ├── markdownContributors.js │ ├── fixConfig.js │ ├── markdownBody.js │ ├── markdownPullRequests.js │ └── markdownIssues.js ├── test ├── payload │ ├── falseConfig.js │ ├── stargazers.js │ ├── releases.js │ ├── commits.js │ ├── issues.opened.json │ ├── issues.js │ └── pullRequests.js ├── bin │ ├── getSearchIssues.test.js │ ├── getReleases.test.js │ ├── postCreateLabel.test.js │ ├── getContributors.test.js │ ├── getAllPullRequests.test.js │ ├── getStargazers.test.js │ ├── getCommits.test.js │ ├── getAllIssues.test.js │ ├── typeCheck.test.js │ ├── postCreateIssues.test.js │ └── constants.test.js ├── markdown │ ├── getDate.test.js │ ├── fixConfig.test.js │ ├── checkDuplicates.test.js │ ├── getLongMonth.test.js │ ├── markdownBody.test.js │ ├── getNumDayFromLongDay.test.js │ ├── markdownContributors.test.js │ ├── markdownStargazers.test.js │ ├── markdownCommits.test.js │ ├── markdownReleases.test.js │ ├── markdownPullRequests.test.js │ └── markdownIssues.test.js └── weeklyDigest.test.js ├── .env.example ├── jest.config.js ├── .travis.yml ├── .eslintrc.js ├── docs ├── deploy.md ├── configuration.md ├── permissions.md └── GSoC.md ├── LICENSE ├── index.test.js ├── index.js ├── package.json ├── CONTRIBUTING.md ├── .gitignore ├── CODE_OF_CONDUCT.md └── README.md /extras/logo/logo.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abhijeetps/weekly-digest/HEAD/extras/logo/logo.PNG -------------------------------------------------------------------------------- /src/bin/typeCheck.js: -------------------------------------------------------------------------------- 1 | const isUndefined = (value) => (value === undefined || value === null || value === ''); 2 | 3 | module.exports = { 4 | isUndefined, 5 | }; 6 | -------------------------------------------------------------------------------- /test/payload/falseConfig.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publishDay: 0, 3 | canPublishIssues: false, 4 | canPublishPullRequests: false, 5 | canPublishContributors: false, 6 | canPublishStargazers: false, 7 | canPublishCommits: false, 8 | canPublishReleases: false, 9 | }; 10 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # The ID of your GitHub App 2 | APP_ID= 3 | WEBHOOK_SECRET=development 4 | 5 | # Use `trace` to get verbose logging or `info` to show less 6 | LOG_LEVEL=debug 7 | 8 | # Go to https://smee.io/new set this to the URL that you are redirected to. 9 | # WEBHOOK_PROXY_URL= 10 | -------------------------------------------------------------------------------- /src/bin/postCreateLabel.js: -------------------------------------------------------------------------------- 1 | module.exports = (context, { 2 | owner, repo, name, color, description, 3 | }) => { 4 | context.log.debug('In postCreateLabel.js..'); 5 | context.github.issues.createLabel({ 6 | owner, 7 | repo, 8 | name, 9 | color, 10 | description, 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /src/bin/postCreateIssues.js: -------------------------------------------------------------------------------- 1 | module.exports = (context, { 2 | owner, repo, title, body, labels, 3 | }) => { 4 | // method is used to create issues 5 | context.log.debug('In postCreateIssues.js...'); 6 | return context.github.issues.create({ 7 | owner, 8 | repo, 9 | title, 10 | body, 11 | labels, 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | verbose: true, 4 | testURL: 'http://localhost/', 5 | collectCoverageFrom: [ 6 | 'src/**/*.js', 7 | 'index.js', 8 | ], 9 | coverageDirectory: './coverage/', 10 | collectCoverage: true, 11 | coverageReporters: ['json', 'lcovonly', 'text', 'clover'], 12 | }; 13 | -------------------------------------------------------------------------------- /src/markdown/getLongMonth.js: -------------------------------------------------------------------------------- 1 | module.exports = (month) => { 2 | const longMonth = [ 3 | 'January', 4 | 'February', 5 | 'March', 6 | 'April', 7 | 'May', 8 | 'June', 9 | 'July', 10 | 'August', 11 | 'September', 12 | 'October', 13 | 'November', 14 | 'December', 15 | ]; 16 | return longMonth[month]; 17 | }; 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | install: 3 | - npm install -g codecov 4 | - npm install 5 | script: 6 | - npm test 7 | - codecov 8 | cache: 9 | directories: 10 | - ~/.npm 11 | notifications: 12 | email: false 13 | node_js: 14 | - '8' 15 | after_success: 16 | - npm run semantic-release 17 | branches: 18 | except: 19 | - /^v\d+\.\d+\.\d+$/ 20 | -------------------------------------------------------------------------------- /src/bin/getReleases.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { owner, repo }) => { 3 | context.log.debug('In getReleases.js...'); 4 | const releases = await context.github.paginate( 5 | context.github.repos.listReleases({ 6 | owner, 7 | repo, 8 | per_page: 100, 9 | }), 10 | (res) => res.data, 11 | ); 12 | return releases; 13 | }; 14 | -------------------------------------------------------------------------------- /src/bin/getContributors.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { owner, repo }) => { 3 | context.log.debug('In getContributors.js...'); 4 | const contributors = await context.github.paginate( 5 | context.github.repos.getContributors({ 6 | owner, 7 | repo, 8 | per_page: 100, 9 | }), 10 | (res) => res.data, 11 | ); 12 | return contributors; 13 | }; 14 | -------------------------------------------------------------------------------- /src/bin/getSearchIssues.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { 3 | owner, repo, date, author, type, 4 | }) => { 5 | context.log.debug('In getSearchIssues.js...'); 6 | const searchIssues = await context.github.search.issues({ 7 | q: `repo:${owner}/${repo} type:${type} author:${author} created:>=${date}`, 8 | per_page: 100, 9 | }); 10 | return searchIssues; 11 | }; 12 | -------------------------------------------------------------------------------- /src/bin/getStargazers.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { owner, repo }) => { 3 | context.log.debug('In getStargazers.js...'); 4 | const stargazers = await context.github.paginate( 5 | context.github.activity.listStargazersForRepo({ 6 | owner, 7 | repo, 8 | per_page: 100, 9 | }), 10 | (res) => res.data, 11 | ); 12 | return stargazers; 13 | }; 14 | -------------------------------------------------------------------------------- /src/bin/getCommits.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { owner, repo, tailDate }) => { 3 | context.log.debug('In getCommits.js...'); 4 | const commits = await context.github.paginate( 5 | context.github.repos.listCommits({ 6 | owner, 7 | repo, 8 | since: tailDate, 9 | per_page: 100, 10 | }), 11 | (res) => res.data, 12 | ); 13 | return commits; 14 | }; 15 | -------------------------------------------------------------------------------- /src/markdown/getDate.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = { 5 | headDate: () => moment.utc().set({ 6 | hour: 0, minute: 0, second: 0, millisecond: 0, 7 | }).format(), 8 | tailDate: () => moment.utc().set({ 9 | hour: 0, minute: 0, second: 0, millisecond: 0, 10 | }).subtract(7, 'days').format(), 11 | getDayBeforeDate: (date) => moment(date).subtract(1, 'days').format(), 12 | }; 13 | -------------------------------------------------------------------------------- /src/bin/getAllPullRequests.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { owner, repo }) => { 3 | // method returns all the pull requests 4 | context.log.debug('In getAllPullRequests.js...'); 5 | const pullRequests = await context.github.paginate( 6 | context.github.pullRequests.list({ 7 | owner, 8 | repo, 9 | state: 'all', 10 | per_page: 100, 11 | }), 12 | (res) => res.data, 13 | ); 14 | return pullRequests; 15 | }; 16 | -------------------------------------------------------------------------------- /src/bin/getAllIssues.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = async (context, { owner, repo, tailDate }) => { 3 | // method returns all the issues and pull requests 4 | context.log.debug('In getAllIssues.js...'); 5 | const issues = await context.github.paginate( 6 | context.github.issues.listForRepo({ 7 | owner, 8 | repo, 9 | state: 'all', 10 | since: tailDate, 11 | per_page: 100, 12 | }), 13 | (res) => res.data, 14 | ); 15 | return issues; 16 | }; 17 | -------------------------------------------------------------------------------- /src/markdown/getNumDayFromLongDay.js: -------------------------------------------------------------------------------- 1 | module.exports = (day) => { 2 | if (typeof day === 'number' && day >= 0 && day < 7) { 3 | return day; 4 | } 5 | const longDay = [ 6 | 'sunday', 7 | 'monday', 8 | 'tuesday', 9 | 'wednesday', 10 | 'thursday', 11 | 'friday', 12 | 'saturday', 13 | ]; 14 | for (let i = 0; i < 7; i += 1) { 15 | if (longDay[i].includes(String(day).toLowerCase())) { 16 | return i; 17 | } 18 | } 19 | 20 | return undefined; 21 | }; 22 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | commonjs: true, 5 | es6: true, 6 | 'jest/globals': true 7 | }, 8 | extends: [ 9 | 'airbnb-base', 10 | ], 11 | plugins: [ 12 | 'jest' 13 | ], 14 | globals: { 15 | Atomics: 'readonly', 16 | SharedArrayBuffer: 'readonly', 17 | }, 18 | parserOptions: { 19 | ecmaVersion: 2018, 20 | }, 21 | rules: { 22 | "max-len": ["warn"] 23 | }, 24 | ignorePatterns: ["coverage/", "node_modules/"] 25 | }; 26 | -------------------------------------------------------------------------------- /docs/deploy.md: -------------------------------------------------------------------------------- 1 | # Deploying 2 | 3 | If you would like to run your own instance of this app, see the [docs for deployment](https://probot.github.io/docs/deployment/). 4 | 5 | This app requires the following **Permissions & Events** for the GitHub App: 6 | 7 | - Issues - **Read** and **Write** 8 | - Pull Requests - **Read** 9 | - Commits - **Read** 10 | - Contributors - **Read** 11 | - Stargazers - **Read** 12 | - Releases - **Read** 13 | - Label - **Write** 14 | - Single File - **Read** 15 | - Path: _.github/weekly-digest.yml_ 16 | -------------------------------------------------------------------------------- /src/bin/constants.js: -------------------------------------------------------------------------------- 1 | const INSTALLATION_EVENTS = ['installation.created', 'installation_repositories']; 2 | const DEFAULT_CONFIG = { 3 | publishDay: 0, 4 | canPublishIssues: true, 5 | canPublishPullRequests: true, 6 | canPublishContributors: true, 7 | canPublishStargazers: true, 8 | canPublishCommits: true, 9 | canPublishReleases: true, 10 | }; 11 | const INTERVAL = 12 * 60 * 60 * 1000; 12 | const SCHEDULE_REPOSITORY_EVENT = 'schedule.repository'; 13 | 14 | module.exports = { 15 | INSTALLATION_EVENTS, 16 | DEFAULT_CONFIG, 17 | INTERVAL, 18 | SCHEDULE_REPOSITORY_EVENT, 19 | }; 20 | -------------------------------------------------------------------------------- /src/markdown/checkDuplicates.js: -------------------------------------------------------------------------------- 1 | const getSearchIssues = require('../bin/getSearchIssues'); 2 | const getDate = require('./getDate'); 3 | 4 | module.exports = async (context, { owner, repo, headDate }) => { 5 | context.log.debug('In checkDuplicates.js...'); 6 | const author = 'app/weekly-digest'; 7 | const type = 'issues'; 8 | const date = getDate.getDayBeforeDate(headDate).substr(0, 19); 9 | const issues = await getSearchIssues(context, { 10 | owner, repo, date, author, type, 11 | }); 12 | const totalCount = issues.data.total_count; 13 | if (totalCount >= 1) { 14 | return { hasDuplicates: true, url: issues.data.items[0].html_url }; 15 | } 16 | return { hasDuplicates: false, url: undefined }; 17 | }; 18 | -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | ## Configuring your applications 2 | 3 | The app provides features to customize your application. To configure your application, 4 | 1. Create a file _.github/weekly-digest.yml_ in your repository, where the app has been installed. 5 | 2. Add the following configuration in the file: 6 | ```yaml 7 | # Configuration for weekly-digest - https://github.com/apps/weekly-digest 8 | publishDay: sun 9 | canPublishIssues: true 10 | canPublishPullRequests: true 11 | canPublishContributors: true 12 | canPublishStargazers: true 13 | canPublishCommits: true 14 | ``` 15 | 3. Save the file and you are ready to go! Weekly Digest will read the configuration from your repository and will work accordingly. 16 | -------------------------------------------------------------------------------- /test/bin/getSearchIssues.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getSearchIssues = require('../../src/bin/getSearchIssues'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const mock = jest.fn(); 8 | 9 | test('that getSearchIssues is working', async () => { 10 | const context = { 11 | log: { 12 | info: jest.fn(), 13 | debug: jest.fn(), 14 | }, 15 | github: { 16 | search: { 17 | issues: mock.mockReturnValue(), 18 | }, 19 | }, 20 | }; 21 | await getSearchIssues(context, { 22 | q: 'repo:abhijeetps/playground type:issues author:weekly-digest created:>=2018-04-17', 23 | }); 24 | expect(context.github.search.issues).toHaveBeenCalled(); 25 | }); 26 | -------------------------------------------------------------------------------- /test/bin/getReleases.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getReleases = require('../../src/bin/getReleases'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that getReleases is working', async () => { 9 | const context = { 10 | log: { 11 | info: jest.fn(), 12 | debug: jest.fn(), 13 | }, 14 | github: { 15 | paginate: jest.fn(), 16 | repos: { 17 | listReleases: jest.fn(), 18 | }, 19 | }, 20 | }; 21 | await getReleases(context, { 22 | owner: 'abhijeetps', 23 | repo: 'playground', 24 | }); 25 | expect(context.github.paginate).toHaveBeenCalled(); 26 | expect(context.github.repos.listReleases).toHaveBeenCalled(); 27 | }); 28 | -------------------------------------------------------------------------------- /test/bin/postCreateLabel.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const postCreateLabel = require('../../src/bin/postCreateLabel'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that postCreateLable is working', async () => { 9 | const context = { 10 | log: { 11 | info: jest.fn(), 12 | debug: jest.fn(), 13 | }, 14 | github: { 15 | issues: { 16 | createLabel: jest.fn(), 17 | }, 18 | }, 19 | }; 20 | await postCreateLabel(context, { 21 | owner: 'abhijeetps', 22 | repo: 'playground', 23 | name: 'weekly-digest', 24 | color: '9C27B0', 25 | description: '', 26 | }); 27 | expect(context.github.issues.createLabel).toHaveBeenCalled(); 28 | }); 29 | -------------------------------------------------------------------------------- /test/bin/getContributors.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getContributors = require('../../src/bin/getContributors'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that getContributors is working', async () => { 9 | const context = { 10 | log: { 11 | info: jest.fn(), 12 | debug: jest.fn(), 13 | }, 14 | github: { 15 | paginate: jest.fn(), 16 | repos: { 17 | getContributors: jest.fn(), 18 | }, 19 | }, 20 | }; 21 | await getContributors(context, { 22 | owner: 'abhijeetps', 23 | repo: 'playground', 24 | }); 25 | expect(context.github.paginate).toHaveBeenCalled(); 26 | expect(context.github.repos.getContributors).toHaveBeenCalled(); 27 | }); 28 | -------------------------------------------------------------------------------- /test/bin/getAllPullRequests.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getAllPullRequests = require('../../src/bin/getAllPullRequests'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that getPullRequests is working', async () => { 9 | const context = { 10 | log: { 11 | info: jest.fn(), 12 | debug: jest.fn(), 13 | }, 14 | github: { 15 | paginate: jest.fn(), 16 | pullRequests: { 17 | list: jest.fn(), 18 | }, 19 | }, 20 | }; 21 | await getAllPullRequests(context, { 22 | owner: 'abhijeetps', 23 | repo: 'playground', 24 | }); 25 | expect(context.github.paginate).toHaveBeenCalled(); 26 | expect(context.github.pullRequests.list).toHaveBeenCalled(); 27 | }); 28 | -------------------------------------------------------------------------------- /test/bin/getStargazers.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getStargazers = require('../../src/bin/getStargazers'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that getStargazers is working', async () => { 9 | const context = { 10 | log: { 11 | info: jest.fn(), 12 | debug: jest.fn(), 13 | }, 14 | github: { 15 | paginate: jest.fn(), 16 | activity: { 17 | listStargazersForRepo: jest.fn(), 18 | }, 19 | }, 20 | }; 21 | await getStargazers(context, { 22 | owner: 'abhijeetps', 23 | repo: 'playground', 24 | }); 25 | expect(context.github.paginate).toHaveBeenCalled(); 26 | expect(context.github.activity.listStargazersForRepo).toHaveBeenCalled(); 27 | }); 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2018, abhijeetps 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /src/markdown/markdownReleases.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = (releases, headDate, tailDate) => { 5 | let releaseString = '# RELEASES\n'; 6 | let data = releases; 7 | if (!data) { 8 | data = []; 9 | } 10 | data = data.filter((item) => (moment(item.published_at).isBetween(tailDate, headDate))); 11 | if (data.length === 0) { 12 | releaseString += 'Last week there were no releases.\n'; 13 | } else { 14 | releaseString += `Last week there ${(data.length > 1) ? 'were' : 'was'} ${data.length} release${(data.length > 1) ? 's' : ''}.\n`; 15 | data.forEach((item) => { 16 | releaseString += `:rocket: [${item.tag_name.replace(/\n/g, ' ')}${(item.name != null) ? ` ${item.name.replace(/\n/g, ' ')}` : ''}](${item.html_url})\n`; 17 | }); 18 | } 19 | return releaseString; 20 | }; 21 | -------------------------------------------------------------------------------- /test/bin/getCommits.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getCommits = require('../../src/bin/getCommits'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const tailDate = moment.utc().subtract(7, 'days').format(); 8 | 9 | test('that getCommits is working', async () => { 10 | const context = { 11 | log: { 12 | info: jest.fn(), 13 | debug: jest.fn(), 14 | }, 15 | github: { 16 | paginate: jest.fn(), 17 | repos: { 18 | listCommits: jest.fn(), 19 | }, 20 | }, 21 | 22 | }; 23 | await getCommits(context, { 24 | owner: 'abhijeetps', 25 | repo: 'playground', 26 | tailDate, 27 | }); 28 | expect(context.github.paginate).toHaveBeenCalled(); 29 | expect(context.github.repos.listCommits).toHaveBeenCalled(); 30 | }); 31 | -------------------------------------------------------------------------------- /test/markdown/getDate.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getDate = require('../../src/markdown/getDate'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that headDate method returns current date', () => { 9 | const date = moment.utc().format(); 10 | expect(getDate.headDate()).toEqual(date); 11 | }); 12 | 13 | test('that tailDate method returns current date - 7 days', () => { 14 | const date = moment.utc().subtract(7, 'days').format(); 15 | expect(getDate.tailDate()).toEqual(date); 16 | }); 17 | 18 | test('that checks if getDayBeforeDate method returns day before today', () => { 19 | const date = moment.utc().subtract(1, 'days').format(); 20 | const testDate = moment.utc('2018-04-24'); 21 | expect(getDate.getDayBeforeDate(testDate)).toEqual(date); 22 | }); 23 | -------------------------------------------------------------------------------- /test/bin/getAllIssues.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const getAllIssues = require('../../src/bin/getAllIssues'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const tailDate = moment.utc().subtract(7, 'days').format(); 8 | 9 | test('that getAllIssues is working', async () => { 10 | const context = { 11 | log: { 12 | info: jest.fn(), 13 | debug: jest.fn(), 14 | }, 15 | github: { 16 | paginate: jest.fn(), 17 | issues: { 18 | listForRepo: jest.fn(), 19 | }, 20 | }, 21 | }; 22 | await getAllIssues(context, { 23 | owner: 'abhijeetps', 24 | repo: 'playground', 25 | tailDate, 26 | }); 27 | expect(context.github.paginate).toHaveBeenCalled(); 28 | expect(context.github.issues.listForRepo).toHaveBeenCalled(); 29 | }); 30 | -------------------------------------------------------------------------------- /test/bin/typeCheck.test.js: -------------------------------------------------------------------------------- 1 | const { isUndefined } = require('../../src/bin/typeCheck'); 2 | 3 | describe('typeCheck', () => { 4 | describe('isUndefined', () => { 5 | test('isUndefined should return true for undefined value', () => { 6 | expect(isUndefined(undefined)).toBeTruthy(); 7 | }); 8 | test('isUndefined should return true for null value', () => { 9 | expect(isUndefined(null)).toBeTruthy(); 10 | }); 11 | test('isUndefined should return true for empty string', () => { 12 | expect(isUndefined('')).toBeTruthy(); 13 | }); 14 | test('isUndefined should return false for non-empty string', () => { 15 | expect(isUndefined('somestring')).toBeFalsy(); 16 | }); 17 | test('isUndefined should return false for numbers', () => { 18 | expect(isUndefined(12)).toBeFalsy(); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/bin/postCreateIssues.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const postCreateIssues = require('../../src/bin/postCreateIssues'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | 8 | test('that postCreateIssues is working', async () => { 9 | const context = { 10 | log: { 11 | info: jest.fn(), 12 | debug: jest.fn(), 13 | }, 14 | github: { 15 | issues: { 16 | create: jest.fn(), 17 | }, 18 | }, 19 | }; 20 | await postCreateIssues(context, { 21 | owner: 'abhijeetps', 22 | repo: 'playground', 23 | title: 'Weekly Digest (17th April 2018 - 24th April 2018)', 24 | body: 'Last week, abhijeetps just started working on probot/weekly-digest.', 25 | labels: 'weekly-digest', 26 | }); 27 | expect(context.github.issues.create).toHaveBeenCalled(); 28 | }); 29 | -------------------------------------------------------------------------------- /src/markdown/markdownCommits.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = (commits, headDate, tailDate) => { 5 | let commitsString = '# COMMITS\n'; 6 | let data = commits; 7 | if (!data) { 8 | data = []; 9 | } 10 | 11 | data = data.filter((item) => (moment(item.commit.committer.date).isBetween(tailDate, headDate) && item.author.login !== 'weekly-digest[bot]')); 12 | 13 | if (data.length === 0) { 14 | commitsString += 'Last week there were no commits.\n'; 15 | } else { 16 | commitsString += `Last week there ${(data.length > 1) ? 'were' : 'was'} ${data.length} commit${(data.length > 1) ? 's' : ''}.\n`; 17 | data.forEach((item) => { 18 | commitsString += `:hammer_and_wrench: [${item.commit.message.replace(/\n/g, ' ')}](${item.html_url}) by [${item.author.login}](${item.author.html_url})\n`; 19 | }); 20 | } 21 | return commitsString; 22 | }; 23 | -------------------------------------------------------------------------------- /test/markdown/fixConfig.test.js: -------------------------------------------------------------------------------- 1 | const fixConfig = require('../../src/markdown/fixConfig'); 2 | 3 | const emptyConfig = {}; 4 | const testConfig1 = { 5 | publishDay: 0, 6 | canPublishIssues: true, 7 | canPublishPullRequests: true, 8 | }; 9 | const config = { 10 | publishDay: 0, 11 | canPublishIssues: true, 12 | canPublishPullRequests: true, 13 | canPublishContributors: true, 14 | canPublishStargazers: true, 15 | canPublishCommits: true, 16 | canPublishReleases: true, 17 | }; 18 | test('that returns and fixes configs', () => { 19 | expect(fixConfig(emptyConfig)).toBeDefined(); 20 | expect(fixConfig(emptyConfig)).toEqual(config); 21 | }); 22 | 23 | test('that returns and fixes configs if some configs are missing', () => { 24 | expect(fixConfig(testConfig1)).toBeDefined(); 25 | expect(fixConfig(testConfig1)).toEqual(config); 26 | }); 27 | 28 | test('that checks config if the received config is null', () => { 29 | expect(fixConfig(testConfig1)).toBeDefined(); 30 | expect(fixConfig(null)).toEqual(config); 31 | }); 32 | -------------------------------------------------------------------------------- /src/markdown/markdownStargazers.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = (stargazers, headDate, tailDate) => { 5 | let stargazersString = '# STARGAZERS\n'; 6 | let data = stargazers; 7 | if (!data) { 8 | data = []; 9 | } 10 | data = data.filter((item) => (moment(item.starred_at).isBetween(tailDate, headDate))); 11 | if (data.length === 0) { 12 | stargazersString += 'Last week there were no stargazers.\n'; 13 | } else { 14 | if (data.length === 1) { 15 | stargazersString += `Last week there was ${data.length} stargazer.\n`; 16 | } else { 17 | stargazersString += `Last week there were ${data.length} stargazers.\n`; 18 | } 19 | data.forEach((item) => { 20 | stargazersString += `:star: [${item.user.login}](${item.user.html_url})\n`; 21 | }); 22 | if (data.length === 1) { 23 | stargazersString += 'You are the star! :star2:\n'; 24 | } else { 25 | stargazersString += 'You all are the stars! :star2:\n'; 26 | } 27 | } 28 | return stargazersString; 29 | }; 30 | -------------------------------------------------------------------------------- /index.test.js: -------------------------------------------------------------------------------- 1 | const { Application } = require('probot'); 2 | const createScheduler = require('probot-scheduler'); 3 | const { SCHEDULE_REPOSITORY_EVENT } = require('./src/bin/constants'); 4 | 5 | const myProbotApp = require('.'); 6 | 7 | describe.skip('My Probot app', () => { 8 | let app; 9 | let github; 10 | 11 | beforeEach(() => { 12 | app = new Application(); 13 | app.load(myProbotApp); 14 | github = { 15 | issues: { 16 | createLabel: jest.fn().mockReturnValue(Promise.resolve({})), 17 | }, 18 | }; 19 | app.auth = () => Promise.resolve(github); 20 | createScheduler(app); 21 | }); 22 | 23 | it(`initCreateWeeklyDigest to have been called when it receives ${SCHEDULE_REPOSITORY_EVENT}`, async () => { 24 | const initCreateWeeklyDigest = jest.fn(); 25 | await app.receive({ 26 | event: SCHEDULE_REPOSITORY_EVENT, 27 | }); 28 | expect(initCreateWeeklyDigest).toHaveBeenCalled(); 29 | }); 30 | }); 31 | 32 | // For more information about testing with Jest see: 33 | // https://facebook.github.io/jest/ 34 | -------------------------------------------------------------------------------- /src/bin/weeklyDigest.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | const getLongMonth = require('../markdown/getLongMonth'); 5 | const markdownBody = require('../markdown/markdownBody'); 6 | 7 | const postCreateIssues = require('./postCreateIssues'); 8 | 9 | module.exports = async (context, { 10 | owner, repo, headDate, tailDate, 11 | }, config) => { 12 | context.log.debug('In weeklyDigest.js...'); 13 | const headDateObject = moment(headDate).toObject(); 14 | const tailDateObject = moment(tailDate).toObject(); 15 | const title = `Weekly Digest (${tailDateObject.date} ${getLongMonth(tailDateObject.months)}, ${tailDateObject.years} - ${headDateObject.date} ${getLongMonth(headDateObject.months)}, ${headDateObject.years})`; 16 | const body = await markdownBody(context, { 17 | owner, repo, headDate, tailDate, 18 | }, config); 19 | const labels = ['weekly-digest']; 20 | context.log.debug(`${title} \n${labels} \n${body}`); 21 | postCreateIssues(context, { 22 | owner, repo, title, body, labels, 23 | }); 24 | return { title, labels, body }; 25 | }; 26 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const createScheduler = require('probot-scheduler'); 2 | const moment = require('moment'); 3 | 4 | const { INSTALLATION_EVENTS, INTERVAL, SCHEDULE_REPOSITORY_EVENT } = require('./src/bin/constants'); 5 | const { manageAppInstallation } = require('./src/bin/manageAppInstallation'); 6 | const { initCreateWeeklyDigest } = require('./src/bin/initCreateWeeklyDigest'); 7 | 8 | module.exports = (app) => { 9 | app.log('Weekly Digest app is running successfully.'); 10 | 11 | app.on(INSTALLATION_EVENTS, async (context) => { 12 | context.log.debug('Weekly Digest installed successfully.'); 13 | context.log.debug(`App is running as per ${context.event}`); 14 | context.log.debug(`Local Time: ${moment().format()}`); 15 | await manageAppInstallation(context); 16 | }); 17 | 18 | createScheduler(app, { interval: INTERVAL }); 19 | app.on(SCHEDULE_REPOSITORY_EVENT, async (context) => { 20 | context.log.debug('App is running as per schedule.repository'); 21 | context.log.debug(`Local Time: ${moment().format()}`); 22 | await initCreateWeeklyDigest(context); 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /src/markdown/markdownContributors.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = (commits, headDate, tailDate) => { 5 | let data = commits; 6 | if (!data) { 7 | data = []; 8 | } 9 | data = data.filter((item) => (moment(item.commit.committer.date).isBetween(tailDate, headDate) && item.author.login !== 'weekly-digest[bot]')); 10 | let contributorsString = '# CONTRIBUTORS\n'; 11 | if (data.length === 0) { 12 | contributorsString += 'Last week there were no contributors.\n'; 13 | } else { 14 | const contributors = []; 15 | data.forEach((item) => { 16 | contributors.push({ login: item.author.login, html_url: item.author.html_url }); 17 | }); 18 | const uniqueContributors = Object.values(contributors.reduce((acc, cul) => Object.assign(acc, { [cul.login]: cul }), {})); 19 | contributorsString += `Last week there ${(uniqueContributors.length > 1) ? 'were' : 'was'} ${uniqueContributors.length} contributor${(uniqueContributors.length > 1) ? 's' : ''}.\n`; 20 | uniqueContributors.forEach((item) => { 21 | contributorsString += `:bust_in_silhouette: [${item.login}](${item.html_url})\n`; 22 | }); 23 | } 24 | return contributorsString; 25 | }; 26 | -------------------------------------------------------------------------------- /src/bin/manageAppInstallation.js: -------------------------------------------------------------------------------- 1 | const getDate = require('../markdown/getDate'); 2 | const weeklyDigest = require('./weeklyDigest'); 3 | const postCreateLabel = require('./postCreateLabel'); 4 | const { DEFAULT_CONFIG } = require('./constants'); 5 | 6 | const manageAppInstallation = async (context) => { 7 | const headDate = getDate.headDate(); 8 | const tailDate = getDate.tailDate(); 9 | const config = DEFAULT_CONFIG; 10 | let repoList = []; 11 | if (context.event === 'installation' && context.payload.action === 'created') { 12 | repoList = context.payload.repositories; 13 | context.log.debug(repoList); 14 | } else if (context.event === 'installation_repositories') { 15 | repoList = context.payload.repositories_added; 16 | } 17 | repoList.forEach(async (item) => { 18 | const [owner, repo] = item.full_name.split('/'); 19 | context.log.debug(`Repository: ${owner}/${repo}`); 20 | await postCreateLabel(context, { 21 | owner, repo, name: 'weekly-digest', color: '9C27B0', description: '', 22 | }); 23 | await weeklyDigest(context, { 24 | owner, repo, headDate, tailDate, 25 | }, config); 26 | }); 27 | }; 28 | 29 | module.exports = { 30 | manageAppInstallation, 31 | }; 32 | -------------------------------------------------------------------------------- /test/markdown/checkDuplicates.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const checkDuplicates = require('../../src/markdown/checkDuplicates'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment.utc().format(); 8 | 9 | const mock = jest.fn(); 10 | 11 | test.skip('that checkDuplicates is working', async () => { 12 | const owner = 'abhijeetps'; 13 | const repo = 'playground'; 14 | const getDate = { 15 | getDayBeforeDate: mock, 16 | }; 17 | const context = { 18 | log: { 19 | info: jest.fn(), 20 | debug: jest.fn(), 21 | }, 22 | github: { 23 | search: { 24 | issues: mock.mockReturnValue(Promise.resolve({ 25 | data: { 26 | total_count: 1, 27 | items: [{ 28 | html_url: 'https://github.com/aps120797/playground', 29 | }], 30 | }, 31 | })), 32 | }, 33 | }, 34 | }; 35 | await checkDuplicates(context, { 36 | owner: 'abhijeetps', 37 | repo: 'playground', 38 | headDate, 39 | }); 40 | 41 | expect(getDate.getDayBeforeDate).toHaveBeenCalled(); 42 | expect(context.github.search.issues()).toHaveBeenCalledWith(context, { owner, repo, headDate }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/markdown/getLongMonth.test.js: -------------------------------------------------------------------------------- 1 | const getLongDate = require('../../src/markdown/getLongMonth'); 2 | 3 | test('that passing 0 returns January', () => { 4 | expect(getLongDate(0)).toBe('January'); 5 | }); 6 | test('that passing 1 returns February', () => { 7 | expect(getLongDate(1)).toBe('February'); 8 | }); 9 | test('that passing 2 returns March', () => { 10 | expect(getLongDate(2)).toBe('March'); 11 | }); 12 | test('that passing 3 returns April', () => { 13 | expect(getLongDate(3)).toBe('April'); 14 | }); 15 | test('that passing 4 returns May', () => { 16 | expect(getLongDate(4)).toBe('May'); 17 | }); 18 | test('that passing 5 returns June', () => { 19 | expect(getLongDate(5)).toBe('June'); 20 | }); 21 | test('that passing 6 returns July', () => { 22 | expect(getLongDate(6)).toBe('July'); 23 | }); 24 | test('that passing 7 returns August', () => { 25 | expect(getLongDate(7)).toBe('August'); 26 | }); 27 | test('that passing 8 returns September', () => { 28 | expect(getLongDate(8)).toBe('September'); 29 | }); 30 | test('that passing 9 returns October', () => { 31 | expect(getLongDate(9)).toBe('October'); 32 | }); 33 | test('that passing 10 returns November', () => { 34 | expect(getLongDate(10)).toBe('November'); 35 | }); 36 | test('that passing 11 returns December', () => { 37 | expect(getLongDate(11)).toBe('December'); 38 | }); 39 | -------------------------------------------------------------------------------- /docs/permissions.md: -------------------------------------------------------------------------------- 1 | # Webhook Events 2 | - `installation.created` 3 | - `installation_repositories` 4 | 5 | # Addtional Events 6 | - schedule.repository ([probot-scheduler](https://www.npmjs.com/package/probot-scheduler)) 7 | 8 | # Extentions Used 9 | - probot-scheduler (https://www.npmjs.com/package/probot-scheduler) 10 | - probot-config (https://www.npmjs.com/package/probot-config) 11 | 12 | # Octokit REST APIs 13 | - [context.github.issues.createLabel](https://octokit.github.io/rest.js/#api-Issues-createLabel) 14 | - [context.github.issues.create](https://octokit.github.io/rest.js/#api-Issues-create) 15 | - [context.github.issues.getForRepo](https://octokit.github.io/rest.js/#api-Issues-getForRepo) 16 | - [context.github.pullRequests.getAll](https://octokit.github.io/rest.js/#api-PullRequests-getAll) 17 | - [context.github.repos.getCommits](https://octokit.github.io/rest.js/#api-Repos-getCommits) 18 | - [context.github.repos.getContributors](https://octokit.github.io/rest.js/#api-Repos-getContributors) 19 | - [context.github.repos.getReleases](https://octokit.github.io/rest.js/#api-Repos-getReleases) 20 | - [context.github.search.issues](https://octokit.github.io/rest.js/#api-Search-issues) 21 | - [context.github.activity.getStargazersForRepo](https://octokit.github.io/rest.js/#api-Activity-getStargazersForRepo) 22 | 23 | -------------------------------------------------------------------------------- /src/markdown/fixConfig.js: -------------------------------------------------------------------------------- 1 | const { isUndefined } = require('../bin/typeCheck'); 2 | const { DEFAULT_CONFIG } = require('../bin/constants'); 3 | 4 | 5 | module.exports = (config) => { 6 | let modifiedConfig = config; 7 | 8 | if (isUndefined(modifiedConfig)) { 9 | modifiedConfig = DEFAULT_CONFIG; 10 | } else { 11 | if (isUndefined(modifiedConfig.publishDay)) { 12 | modifiedConfig.publishDay = DEFAULT_CONFIG.publishDay; 13 | } 14 | if (isUndefined(modifiedConfig.canPublishIssues)) { 15 | modifiedConfig.canPublishIssues = DEFAULT_CONFIG.canPublishIssues; 16 | } 17 | if (isUndefined(modifiedConfig.canPublishPullRequests)) { 18 | modifiedConfig.canPublishPullRequests = DEFAULT_CONFIG.canPublishPullRequests; 19 | } 20 | if (isUndefined(modifiedConfig.canPublishContributors)) { 21 | modifiedConfig.canPublishContributors = DEFAULT_CONFIG.canPublishContributors; 22 | } 23 | if (isUndefined(modifiedConfig.canPublishStargazers)) { 24 | modifiedConfig.canPublishStargazers = DEFAULT_CONFIG.canPublishContributors; 25 | } 26 | if (isUndefined(modifiedConfig.canPublishCommits)) { 27 | modifiedConfig.canPublishCommits = DEFAULT_CONFIG.canPublishCommits; 28 | } 29 | if (isUndefined(modifiedConfig.canPublishReleases)) { 30 | modifiedConfig.canPublishReleases = DEFAULT_CONFIG.canPublishReleases; 31 | } 32 | } 33 | return modifiedConfig; 34 | }; 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weekly-digest", 3 | "version": "0.0.0-development", 4 | "description": "", 5 | "author": "abhijeetps ", 6 | "license": "ISC", 7 | "repository": "https://github.com/probot/weekly-digest.git", 8 | "scripts": { 9 | "dev": "nodemon --exec \"ENVIRONMENT=development npm start\"", 10 | "prodlike": "nodemon --exec \"LOG_LEVEL=info npm start\"", 11 | "start": "probot run ./index.js", 12 | "lint": "eslint \"**/*.js\" --fix", 13 | "test": "eslint \"**/*.js\" && jest", 14 | "test:watch": "jest --watch --notify --notifyMode=change --coverage", 15 | "travis-deploy-once": "travis-deploy-once", 16 | "semantic-release": "semantic-release" 17 | }, 18 | "dependencies": { 19 | "mockdate": "2.0.2", 20 | "moment": "2.22.2", 21 | "nock": "9.4.4", 22 | "probot": "7.5.3", 23 | "probot-config": "1.1.0", 24 | "probot-scheduler": "1.2.0" 25 | }, 26 | "devDependencies": { 27 | "eslint": "6.8.0", 28 | "eslint-config-airbnb-base": "14.1.0", 29 | "eslint-plugin-import": "2.20.2", 30 | "eslint-plugin-jest": "^23.13.1", 31 | "eslint-plugin-prettier": "3.1.3", 32 | "jest": "23.4.2", 33 | "nodemon": "1.18.3", 34 | "prettier": "2.0.5", 35 | "semantic-release": "15.9.3", 36 | "smee-client": "1.0.2", 37 | "travis-deploy-once": "5.0.1" 38 | }, 39 | "engines": { 40 | "node": ">= 8.3.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/bin/initCreateWeeklyDigest.js: -------------------------------------------------------------------------------- 1 | const getConfig = require('probot-config'); 2 | 3 | const moment = require('moment'); 4 | const getDate = require('../markdown/getDate'); 5 | const getNumDayFromLongDay = require('../markdown/getNumDayFromLongDay'); 6 | const fixConfig = require('../markdown/fixConfig'); 7 | const weeklyDigest = require('./weeklyDigest'); 8 | const checkDuplicates = require('../markdown/checkDuplicates'); 9 | 10 | const initCreateWeeklyDigest = async (context) => { 11 | const { owner, repo } = context.repo(); 12 | context.log.debug(`Repository: ${owner}/${repo}`); 13 | const headDate = getDate.headDate(); 14 | const tailDate = getDate.tailDate(); 15 | const { hasDuplicates, url } = await checkDuplicates(context, { owner, repo, headDate }); 16 | if (hasDuplicates) { 17 | context.log.debug(`Weekly Digest for this week has already been published for ${owner}/${repo}`); 18 | context.log.debug(`URL: ${url}`); 19 | return; 20 | } 21 | let config = await getConfig(context, 'weekly-digest.yml'); 22 | config = fixConfig(config); 23 | context.log.debug(`Publish Day: ${getNumDayFromLongDay(config.publishDay)}, Today: ${moment.utc().day()}`); 24 | if (moment.utc().day() === getNumDayFromLongDay(config.publishDay)) { 25 | await weeklyDigest(context, { 26 | owner, repo, headDate, tailDate, 27 | }, config); 28 | } 29 | }; 30 | 31 | module.exports = { 32 | initCreateWeeklyDigest, 33 | }; 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [fork]: /fork 4 | [pr]: /compare 5 | [style]: https://github.com/airbnb/javascript 6 | [code-of-conduct]: CODE_OF_CONDUCT.md 7 | 8 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. 9 | 10 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 11 | 12 | ## Submitting a pull request 13 | 14 | 1. [Fork][fork] and clone the repository 15 | 1. Configure and install the dependencies: `npm install` 16 | 1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so no need to lint seperately 17 | 1. Create a new branch: `git checkout -b my-branch-name` 18 | 1. Make your change, add tests, and make sure the tests still pass 19 | 1. Push to your fork and [submit a pull request][pr] 20 | 1. Pat your self on the back and wait for your pull request to be reviewed and merged. 21 | 22 | Here are a few things you can do that will increase the likelihood of your pull request being accepted: 23 | 24 | - Follow the [style guide][style] which is using standard. Any linting errors should be shown when running `npm test` 25 | - Write and update tests. 26 | - Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. 27 | - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 28 | 29 | Work in Progress pull request are also welcome to get feedback early on, or if there is something blocked you. 30 | 31 | ## Resources 32 | 33 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) 34 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) 35 | - [GitHub Help](https://help.github.com) 36 | -------------------------------------------------------------------------------- /test/payload/stargazers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | emptyStargazers: { 3 | data: [], 4 | }, 5 | nullStargazers: { 6 | data: null, 7 | }, 8 | uselessStargazers: { 9 | data: [ 10 | { 11 | user: { 12 | login: 'wilhelmklopp', 13 | html_url: 'https://github.com/wilhelmklopp', 14 | }, 15 | starred_at: '2018-04-24T00:00:00Z', 16 | }, 17 | { 18 | user: { 19 | login: 'gr2m', 20 | html_url: 'https://github.com/gr2m', 21 | }, 22 | starred_at: '2018-04-16T00:00:00Z', 23 | }, 24 | ], 25 | }, 26 | manyStargazers: { 27 | data: [ 28 | { 29 | user: { 30 | login: 'wilhelmklopp', 31 | html_url: 'https://github.com/wilhelmklopp', 32 | }, 33 | starred_at: '2018-04-21T00:00:00Z', 34 | }, 35 | { 36 | user: { 37 | login: 'abhijeetps', 38 | html_url: 'https://github.com/abhijeetps', 39 | }, 40 | starred_at: '2018-04-20T00:00:00Z', 41 | }, 42 | { 43 | user: { 44 | login: 'gr2m', 45 | html_url: 'https://github.com/gr2m', 46 | }, 47 | starred_at: '2018-04-19T00:00:00Z', 48 | }, 49 | ], 50 | }, 51 | allStargazers: { 52 | data: [ 53 | { 54 | user: { 55 | login: 'wilhelmklopp', 56 | html_url: 'https://github.com/wilhelmklopp', 57 | }, 58 | starred_at: '2018-04-24T00:00:00Z', 59 | }, 60 | { 61 | user: { 62 | login: 'abhijeetps', 63 | html_url: 'https://github.com/abhijeetps', 64 | }, 65 | starred_at: '2018-04-20T00:00:00Z', 66 | }, 67 | { 68 | user: { 69 | login: 'gr2m', 70 | html_url: 'https://github.com/gr2m', 71 | }, 72 | starred_at: '2018-04-16T00:00:00Z', 73 | }, 74 | ], 75 | }, 76 | }; 77 | -------------------------------------------------------------------------------- /test/markdown/markdownBody.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownBody = require('../../src/markdown/markdownBody'); 5 | const { DEFAULT_CONFIG } = require('../../src/bin/constants'); 6 | const falseConfig = require('../payload/falseConfig'); 7 | 8 | MockDate.set(moment.utc('2018-04-24')); 9 | const headDate = moment.utc().format(); 10 | const tailDate = moment.utc().subtract(7, 'days').format(); 11 | 12 | test('that markdownBody works', () => { 13 | const owner = 'abhijeetps'; 14 | const repo = 'playground'; 15 | const context = { 16 | log: { 17 | info: jest.fn(), 18 | debug: jest.fn(), 19 | }, 20 | github: { 21 | paginate: jest.fn(), 22 | issues: { 23 | listForRepo: jest.fn(), 24 | create: jest.fn(), 25 | }, 26 | pullRequests: { 27 | list: jest.fn(), 28 | }, 29 | repos: { 30 | listCommits: jest.fn(), 31 | listReleases: jest.fn(), 32 | }, 33 | activity: { 34 | listStargazersForRepo: jest.fn(), 35 | }, 36 | }, 37 | }; 38 | expect(markdownBody(context, { 39 | owner, repo, headDate, tailDate, 40 | }, DEFAULT_CONFIG)).toBeDefined(); 41 | }); 42 | 43 | test('that markdownBody works when the configs defined are all false', () => { 44 | const owner = 'abhijeetps'; 45 | const repo = 'playground'; 46 | const context = { 47 | log: { 48 | info: jest.fn(), 49 | debug: jest.fn(), 50 | }, 51 | github: { 52 | paginate: jest.fn(), 53 | issues: { 54 | listForRepo: jest.fn(), 55 | create: jest.fn(), 56 | }, 57 | pullRequests: { 58 | list: jest.fn(), 59 | }, 60 | repos: { 61 | listCommits: jest.fn(), 62 | listReleases: jest.fn(), 63 | }, 64 | activity: { 65 | listStargazersForRepo: jest.fn(), 66 | }, 67 | }, 68 | }; 69 | expect(markdownBody(context, { 70 | owner, repo, headDate, tailDate, 71 | }, falseConfig)).toBeDefined(); 72 | }); 73 | -------------------------------------------------------------------------------- /test/weeklyDigest.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const weeklyDigest = require('../src/bin/weeklyDigest'); 5 | const { DEFAULT_CONFIG } = require('../src/bin/constants'); 6 | const falseConfig = require('./payload/falseConfig'); 7 | 8 | MockDate.set(moment.utc('2018-04-24')); 9 | const headDate = moment.utc().format(); 10 | const tailDate = moment.utc().subtract(7, 'days').format(); 11 | 12 | jest.mock('./../src/markdown/markdownBody', () => () => Promise.resolve('This is the markdownBody.')); 13 | 14 | test('that weekly digest is working when configs are defined and is false', async () => { 15 | const owner = 'abhijeetps'; 16 | const repo = 'playground'; 17 | const context = { 18 | log: { 19 | info: jest.fn(), 20 | debug: jest.fn(), 21 | }, 22 | github: { 23 | paginate: jest.fn(), 24 | issues: { 25 | listForRepo: jest.fn(), 26 | create: jest.fn(), 27 | }, 28 | pullRequests: { 29 | list: jest.fn(), 30 | }, 31 | repos: { 32 | listCommits: jest.fn(), 33 | listReleases: jest.fn(), 34 | }, 35 | activity: { 36 | listStargazersForRepo: jest.fn(), 37 | }, 38 | }, 39 | }; 40 | const { title, labels, body } = await weeklyDigest(context, { 41 | owner, repo, headDate, tailDate, 42 | }, DEFAULT_CONFIG); 43 | expect(title).toBeDefined(); 44 | expect(labels).toContain('weekly-digest'); 45 | expect(body).toBeDefined(); 46 | }); 47 | 48 | test('that weekly digest is working when configs are defined and is true', async () => { 49 | const owner = 'abhijeetps'; 50 | const repo = 'playground'; 51 | const context = { 52 | log: { 53 | info: jest.fn(), 54 | debug: jest.fn(), 55 | }, 56 | github: { 57 | paginate: jest.fn(), 58 | issues: { 59 | listForRepo: jest.fn(), 60 | create: jest.fn(), 61 | }, 62 | pullRequests: { 63 | list: jest.fn(), 64 | }, 65 | repos: { 66 | listCommits: jest.fn(), 67 | listReleases: jest.fn(), 68 | }, 69 | activity: { 70 | listStargazersForRepo: jest.fn(), 71 | }, 72 | }, 73 | }; 74 | const { title, labels, body } = await weeklyDigest(context, { 75 | owner, repo, headDate, tailDate, 76 | }, falseConfig); 77 | expect(title).toBeDefined(); 78 | expect(labels).toContain('weekly-digest'); 79 | expect(body).toBeDefined(); 80 | }); 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,code 3 | # Edit at https://www.gitignore.io/?templates=node,code 4 | 5 | ### Code ### 6 | .vscode/* 7 | !.vscode/settings.json 8 | !.vscode/tasks.json 9 | !.vscode/launch.json 10 | !.vscode/extensions.json 11 | 12 | ### Node ### 13 | # Logs 14 | logs 15 | *.log 16 | npm-debug.log* 17 | yarn-debug.log* 18 | yarn-error.log* 19 | lerna-debug.log* 20 | 21 | # Diagnostic reports (https://nodejs.org/api/report.html) 22 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 23 | 24 | # Runtime data 25 | pids 26 | *.pid 27 | *.seed 28 | *.pid.lock 29 | 30 | # Directory for instrumented libs generated by jscoverage/JSCover 31 | lib-cov 32 | 33 | # Coverage directory used by tools like istanbul 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | .nyc_output 39 | 40 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 41 | .grunt 42 | 43 | # Bower dependency directory (https://bower.io/) 44 | bower_components 45 | 46 | # node-waf configuration 47 | .lock-wscript 48 | 49 | # Compiled binary addons (https://nodejs.org/api/addons.html) 50 | build/Release 51 | 52 | # Dependency directories 53 | node_modules/ 54 | jspm_packages/ 55 | 56 | # TypeScript v1 declaration files 57 | typings/ 58 | 59 | # TypeScript cache 60 | *.tsbuildinfo 61 | 62 | # Optional npm cache directory 63 | .npm 64 | 65 | # Optional eslint cache 66 | .eslintcache 67 | 68 | # Optional REPL history 69 | .node_repl_history 70 | 71 | # Output of 'npm pack' 72 | *.tgz 73 | 74 | # Yarn Integrity file 75 | .yarn-integrity 76 | 77 | # dotenv environment variables file 78 | .env 79 | .env.test 80 | 81 | # parcel-bundler cache (https://parceljs.org/) 82 | .cache 83 | 84 | # next.js build output 85 | .next 86 | 87 | # nuxt.js build output 88 | .nuxt 89 | 90 | # rollup.js default build output 91 | dist/ 92 | 93 | # Uncomment the public line if your project uses Gatsby 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 96 | # public 97 | 98 | # Storybook build outputs 99 | .out 100 | .storybook-out 101 | 102 | # vuepress build output 103 | .vuepress/dist 104 | 105 | # Serverless directories 106 | .serverless/ 107 | 108 | # FuseBox cache 109 | .fusebox/ 110 | 111 | # DynamoDB Local files 112 | .dynamodb/ 113 | 114 | # Temporary folders 115 | tmp/ 116 | temp/ 117 | 118 | # Private Keys 119 | *.pem 120 | 121 | # End of https://www.gitignore.io/api/node,code 122 | -------------------------------------------------------------------------------- /test/markdown/getNumDayFromLongDay.test.js: -------------------------------------------------------------------------------- 1 | const getNumDayFromLongDay = require('../../src/markdown/getNumDayFromLongDay'); 2 | 3 | test('that checks if 0 returns 0', () => { 4 | expect(getNumDayFromLongDay(0)).toEqual(0); 5 | }); 6 | test('that checks any invalid day returns undefined', () => { 7 | expect(getNumDayFromLongDay(7)).toBeUndefined(); 8 | }); 9 | test('that checks if 1 returns 1', () => { 10 | expect(getNumDayFromLongDay(1)).toEqual(1); 11 | }); 12 | test('that checks if 2 returns 2', () => { 13 | expect(getNumDayFromLongDay(2)).toEqual(2); 14 | }); 15 | test('that checks if 3 returns 3', () => { 16 | expect(getNumDayFromLongDay(3)).toEqual(3); 17 | }); 18 | test('that checks if 4 returns 4', () => { 19 | expect(getNumDayFromLongDay(4)).toEqual(4); 20 | }); 21 | test('that checks if 5 returns 5', () => { 22 | expect(getNumDayFromLongDay(5)).toEqual(5); 23 | }); 24 | test('that checks if 6 returns 6', () => { 25 | expect(getNumDayFromLongDay(6)).toEqual(6); 26 | }); 27 | 28 | test('that checks if \'sun\' returns 0', () => { 29 | expect(getNumDayFromLongDay('sun')).toBe(0); 30 | }); 31 | test('that checks if \'mon\' returns 1', () => { 32 | expect(getNumDayFromLongDay('mon')).toBe(1); 33 | }); 34 | test('that checks if \'tue\' returns 2', () => { 35 | expect(getNumDayFromLongDay('tue')).toBe(2); 36 | }); 37 | test('that checks if \'wed\' returns 3', () => { 38 | expect(getNumDayFromLongDay('wed')).toBe(3); 39 | }); 40 | test('that checks if \'thu\' returns 4', () => { 41 | expect(getNumDayFromLongDay('thu')).toBe(4); 42 | }); 43 | test('that checks if \'fri\' returns 5', () => { 44 | expect(getNumDayFromLongDay('fri')).toBe(5); 45 | }); 46 | test('that checks if \'sat\' returns 6', () => { 47 | expect(getNumDayFromLongDay('sat')).toBe(6); 48 | }); 49 | 50 | test('that checks if \'Sunday\' returns 0', () => { 51 | expect(getNumDayFromLongDay('Sunday')).toBe(0); 52 | }); 53 | test('that checks if \'Monday\' returns 1', () => { 54 | expect(getNumDayFromLongDay('Monday')).toBe(1); 55 | }); 56 | test('that checks if \'Tuesday\' returns 2', () => { 57 | expect(getNumDayFromLongDay('Tuesday')).toBe(2); 58 | }); 59 | test('that checks if \'Wednesday\' returns 3', () => { 60 | expect(getNumDayFromLongDay('Wednesday')).toBe(3); 61 | }); 62 | test('that checks if \'Thursday\' returns 4', () => { 63 | expect(getNumDayFromLongDay('Thursday')).toBe(4); 64 | }); 65 | test('that checks if \'Friday\' returns 5', () => { 66 | expect(getNumDayFromLongDay('Friday')).toBe(5); 67 | }); 68 | test('that checks if \'Saturday\' returns 6', () => { 69 | expect(getNumDayFromLongDay('Saturday')).toBe(6); 70 | }); 71 | -------------------------------------------------------------------------------- /test/markdown/markdownContributors.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownContributors = require('../../src/markdown/markdownContributors'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment().utc().format(); 8 | const tailDate = moment().utc().subtract(7, 'days').format(); 9 | 10 | const commits = require('../payload/commits'); 11 | 12 | const emptyCommit = commits.emptyCommits.data; 13 | const nullCommit = commits.nullCommits.data; 14 | const uselessCommit = commits.uselessCommits.data; 15 | const allCommits = commits.allCommits.data; 16 | const manyCommits = commits.manyCommits.data; 17 | 18 | test('that checks return string if there are no commits', () => { 19 | expect(markdownContributors(emptyCommit, headDate, tailDate)).toContain('# CONTRIBUTORS'); 20 | expect(markdownContributors(emptyCommit, headDate, tailDate)).toContain('Last week there were no contributors.'); 21 | }); 22 | 23 | test('that checks return string if there are null commits', () => { 24 | expect(markdownContributors(nullCommit, headDate, tailDate)).toContain('# CONTRIBUTORS'); 25 | expect(markdownContributors(nullCommit, headDate, tailDate)).toContain('Last week there were no contributors.'); 26 | }); 27 | 28 | test('that checks return string if there are useless commits', () => { 29 | expect(markdownContributors(uselessCommit, headDate, tailDate)).toContain('# CONTRIBUTORS'); 30 | expect(markdownContributors(uselessCommit, headDate, tailDate)).toContain('Last week there were no contributors.'); 31 | }); 32 | 33 | test('that checks returns string of many contributors', () => { 34 | expect(markdownContributors(manyCommits, headDate, tailDate)).toContain('# CONTRIBUTORS'); 35 | expect(markdownContributors(manyCommits, headDate, tailDate)).toContain('Last week there were 3 contributors.'); 36 | expect(markdownContributors(manyCommits, headDate, tailDate)).toContain(':bust_in_silhouette: [gr2m](https://github.com/gr2m/)'); 37 | expect(markdownContributors(manyCommits, headDate, tailDate)).toContain(':bust_in_silhouette: [wilhelmklopp](https://github.com/wilhelmklopp/)'); 38 | expect(markdownContributors(manyCommits, headDate, tailDate)).toContain('bust_in_silhouette: [abhijeetps](https://github.com/abhijeetps/)'); 39 | }); 40 | 41 | test('that checks return string of some contributors', () => { 42 | expect(markdownContributors(allCommits, headDate, tailDate)).toContain('# CONTRIBUTORS'); 43 | expect(markdownContributors(allCommits, headDate, tailDate)).toContain('Last week there was 1 contributor.'); 44 | expect(markdownContributors(allCommits, headDate, tailDate)).toContain(':bust_in_silhouette: [abhijeetps](https://github.com/abhijeetps/)'); 45 | }); 46 | -------------------------------------------------------------------------------- /test/payload/releases.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | emptyReleases: { 4 | data: [], 5 | }, 6 | nullReleases: { 7 | data: null, 8 | }, 9 | uselessReleases: { 10 | data: [ 11 | { 12 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v1.0.0', 13 | tag_name: 'v1.0.0', 14 | name: 'Release v1.0.0', 15 | published_at: '2018-04-24T00:00:00Z', 16 | }, 17 | { 18 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.0.1', 19 | tag_name: 'v0.0.1', 20 | name: 'Release v0.0.1', 21 | published_at: '2018-04-16T00:00:00Z', 22 | }, 23 | ], 24 | }, 25 | manyReleases: { 26 | data: [ 27 | { 28 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v1.0.0', 29 | tag_name: 'v1.0.0', 30 | name: 'Release v1.0.0', 31 | published_at: '2018-04-21T00:00:00Z', 32 | }, 33 | { 34 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.1.1', 35 | tag_name: 'v0.1.1', 36 | name: 'Release v0.1.1', 37 | published_at: '2018-04-20T00:00:00Z', 38 | }, 39 | { 40 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.0.1', 41 | tag_name: 'v0.0.1', 42 | name: 'Release v0.0.1', 43 | published_at: '2018-04-19T00:00:00Z', 44 | }, 45 | ], 46 | }, 47 | allReleases: { 48 | data: [ 49 | { 50 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v1.0.0', 51 | tag_name: 'v1.0.0', 52 | name: 'Release v1.0.0', 53 | published_at: '2018-04-24T00:00:00Z', 54 | }, 55 | { 56 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.1.1', 57 | tag_name: 'v0.1.1', 58 | name: 'Release v0.1.1', 59 | published_at: '2018-04-21T00:00:00Z', 60 | }, 61 | { 62 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.0.1', 63 | tag_name: 'v0.0.1', 64 | name: 'Release v0.0.1', 65 | published_at: '2018-04-16T00:00:00Z', 66 | }, 67 | ], 68 | }, 69 | nullNameReleases: { 70 | data: [ 71 | { 72 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v1.0.0', 73 | tag_name: 'v1.0.0', 74 | name: null, 75 | published_at: '2018-04-24T00:00:00Z', 76 | }, 77 | { 78 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.1.1', 79 | tag_name: 'v0.1.1', 80 | name: null, 81 | published_at: '2018-04-21T00:00:00Z', 82 | }, 83 | { 84 | html_url: 'https://github.com/abhijeetps/playground/releases/tag/v0.0.1', 85 | tag_name: 'v0.0.1', 86 | name: null, 87 | published_at: '2018-04-16T00:00:00Z', 88 | }, 89 | ], 90 | }, 91 | }; 92 | -------------------------------------------------------------------------------- /test/markdown/markdownStargazers.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownStargazers = require('../../src/markdown/markdownStargazers'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment().utc().format(); 8 | const tailDate = moment().utc().subtract(7, 'days').format(); 9 | 10 | const stargazers = require('../payload/stargazers'); 11 | 12 | const emptyStargazers = stargazers.emptyStargazers.data; 13 | const nullStargazers = stargazers.nullStargazers.data; 14 | const uselessStargazers = stargazers.uselessStargazers.data; 15 | const manyStargazers = stargazers.manyStargazers.data; 16 | const allStargazers = stargazers.allStargazers.data; 17 | 18 | test('that checks return string if stargazers data is empty', () => { 19 | expect(markdownStargazers(emptyStargazers, headDate, tailDate)).toContain('# STARGAZERS'); 20 | expect(markdownStargazers(emptyStargazers, headDate, tailDate)).toContain('Last week there were no stargazers.'); 21 | }); 22 | 23 | test('that checks return string if stargazers data is null', () => { 24 | expect(markdownStargazers(nullStargazers, headDate, tailDate)).toContain('# STARGAZERS'); 25 | expect(markdownStargazers(nullStargazers, headDate, tailDate)).toContain('Last week there were no stargazers.'); 26 | }); 27 | 28 | test('that checks return string if stargazers data is useless', () => { 29 | expect(markdownStargazers(uselessStargazers, headDate, tailDate)).toContain('# STARGAZERS'); 30 | expect(markdownStargazers(uselessStargazers, headDate, tailDate)).toContain('Last week there were no stargazers.'); 31 | }); 32 | 33 | test('that checks return string if there are many stargazers', () => { 34 | expect(markdownStargazers(manyStargazers, headDate, tailDate)).toContain('# STARGAZERS'); 35 | expect(markdownStargazers(manyStargazers, headDate, tailDate)).toContain('Last week there were 3 stargazers.'); 36 | expect(markdownStargazers(manyStargazers, headDate, tailDate)).toContain(':star: [wilhelmklopp](https://github.com/wilhelmklopp)'); 37 | expect(markdownStargazers(manyStargazers, headDate, tailDate)).toContain(':star: [abhijeetps](https://github.com/abhijeetps)'); 38 | expect(markdownStargazers(manyStargazers, headDate, tailDate)).toContain(':star: [gr2m](https://github.com/gr2m)'); 39 | expect(markdownStargazers(manyStargazers, headDate, tailDate)).toContain('You all are the stars! :star2:'); 40 | }); 41 | 42 | test('that checks return string if there are some stargazers', () => { 43 | expect(markdownStargazers(allStargazers, headDate, tailDate)).toContain('# STARGAZERS'); 44 | expect(markdownStargazers(allStargazers, headDate, tailDate)).toContain('Last week there was 1 stargazer.'); 45 | expect(markdownStargazers(allStargazers, headDate, tailDate)).toContain(':star: [abhijeetps](https://github.com/abhijeetps)'); 46 | expect(markdownStargazers(allStargazers, headDate, tailDate)).toContain('You are the star! :star2:'); 47 | }); 48 | -------------------------------------------------------------------------------- /test/markdown/markdownCommits.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownCommits = require('../../src/markdown/markdownCommits'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment().utc().format(); 8 | const tailDate = moment().utc().subtract(7, 'days').format(); 9 | 10 | const commits = require('../payload/commits'); 11 | 12 | const emptyCommit = commits.emptyCommits.data; 13 | const nullCommit = commits.nullCommits.data; 14 | const uselessCommits = commits.uselessCommits.data; 15 | const manyCommits = commits.manyCommits.data; 16 | const allCommits = commits.allCommits.data; 17 | 18 | test('that checks return string if the commit data is empty', () => { 19 | expect(markdownCommits(emptyCommit, headDate, tailDate)).toContain('# COMMITS'); 20 | expect(markdownCommits(emptyCommit, headDate, tailDate)).toContain('Last week there were no commits.'); 21 | }); 22 | 23 | test('that checks return string if the commit data is null', () => { 24 | expect(markdownCommits(nullCommit, headDate, tailDate)).toContain('# COMMITS'); 25 | expect(markdownCommits(nullCommit, headDate, tailDate)).toContain('Last week there were no commits.'); 26 | }); 27 | 28 | test('that checks return string if the commit data is useless', () => { 29 | expect(markdownCommits(uselessCommits, headDate, tailDate)).toContain('# COMMITS'); 30 | expect(markdownCommits(uselessCommits, headDate, tailDate)).toContain('Last week there were no commits.'); 31 | }); 32 | 33 | test('that checks return string if there are many commits', () => { 34 | expect(markdownCommits(manyCommits, headDate, tailDate)).toContain('# COMMITS'); 35 | expect(markdownCommits(manyCommits, headDate, tailDate)).toContain('Last week there were 3 commits.'); 36 | expect(markdownCommits(manyCommits, headDate, tailDate)).toContain(':hammer_and_wrench: [Weekly-Digest commit test3](https://github.com/abhijeetps/playground/commit/commit-sha-3) by [gr2m](https://github.com/gr2m/)'); 37 | expect(markdownCommits(manyCommits, headDate, tailDate)).toContain(':hammer_and_wrench: [Weekly-Digest commit test3](https://github.com/abhijeetps/playground/commit/commit-sha-2) by [wilhelmklopp](https://github.com/wilhelmklopp/)'); 38 | expect(markdownCommits(manyCommits, headDate, tailDate)).toContain(':hammer_and_wrench: [Weekly-Digest commit test3](https://github.com/abhijeetps/playground/commit/commit-sha-1) by [abhijeetps](https://github.com/abhijeetps/)'); 39 | }); 40 | 41 | test('that checks return string if there are commit', () => { 42 | expect(markdownCommits(allCommits, headDate, tailDate)).toContain('# COMMITS'); 43 | expect(markdownCommits(allCommits, headDate, tailDate)).toContain('Last week there was 1 commit.'); 44 | expect(markdownCommits(allCommits, headDate, tailDate)).toContain(':hammer_and_wrench: [Weekly-Digest commit test3](https://github.com/abhijeetps/playground/commit/commit-sha-3) by [abhijeetps](https://github.com/abhijeetps/)'); 45 | }); 46 | -------------------------------------------------------------------------------- /test/bin/constants.test.js: -------------------------------------------------------------------------------- 1 | 2 | const constants = require('../../src/bin/constants'); 3 | 4 | describe('constants', () => { 5 | describe('INTERVAL', () => { 6 | test('INTERVAL value is 12 hours', () => { 7 | expect(constants.INTERVAL).toBeDefined(); 8 | expect(constants.INTERVAL).toEqual(12 * 60 * 60 * 1000); 9 | }); 10 | }); 11 | describe('SCHEDULE_REPOSITORY_EVENT', () => { 12 | test('SCHEDULE_REPOSITORY_EVENT is schedule.repository', () => { 13 | expect(constants.SCHEDULE_REPOSITORY_EVENT).toBeDefined(); 14 | expect(constants.SCHEDULE_REPOSITORY_EVENT).toEqual('schedule.repository'); 15 | }); 16 | }); 17 | describe('DEFAULT_CONFIG', () => { 18 | const TEST_DEFAULT_CONFIG = { 19 | publishDay: 0, 20 | canPublishIssues: true, 21 | canPublishPullRequests: true, 22 | canPublishContributors: true, 23 | canPublishStargazers: true, 24 | canPublishCommits: true, 25 | canPublishReleases: true, 26 | }; 27 | test('DEFAULT_CONFIG should not change', () => { 28 | expect(constants.DEFAULT_CONFIG).toBeDefined(); 29 | expect(constants.DEFAULT_CONFIG).toEqual(TEST_DEFAULT_CONFIG); 30 | }); 31 | test('DEFAULT_CONFIG publishDay is 0 (Sunday)', () => { 32 | expect(constants.DEFAULT_CONFIG.publishDay).toBeDefined(); 33 | expect(constants.DEFAULT_CONFIG.publishDay).toEqual(0); 34 | }); 35 | test('DEFAULT_CONFIG canPublishIssues is true', () => { 36 | expect(constants.DEFAULT_CONFIG.canPublishIssues).toBeDefined(); 37 | expect(constants.DEFAULT_CONFIG.canPublishIssues).toBeTruthy(); 38 | }); 39 | test('DEFAULT_CONFIG canPublishPullRequests is true', () => { 40 | expect(constants.DEFAULT_CONFIG.canPublishPullRequests).toBeDefined(); 41 | expect(constants.DEFAULT_CONFIG.canPublishPullRequests).toBeTruthy(); 42 | }); 43 | test('DEFAULT_CONFIG canPublishContributors is true', () => { 44 | expect(constants.DEFAULT_CONFIG.canPublishContributors).toBeDefined(); 45 | expect(constants.DEFAULT_CONFIG.canPublishContributors).toBeTruthy(); 46 | }); 47 | test('DEFAULT_CONFIG canPublishStargazers is true', () => { 48 | expect(constants.DEFAULT_CONFIG.canPublishStargazers).toBeDefined(); 49 | expect(constants.DEFAULT_CONFIG.canPublishStargazers).toBeTruthy(); 50 | }); 51 | test('DEFAULT_CONFIG canPublishCommits is true', () => { 52 | expect(constants.DEFAULT_CONFIG.canPublishCommits).toBeDefined(); 53 | expect(constants.DEFAULT_CONFIG.canPublishCommits).toBeTruthy(); 54 | }); 55 | test('DEFAULT_CONFIG canPublishReleases is true', () => { 56 | expect(constants.DEFAULT_CONFIG.canPublishReleases).toBeDefined(); 57 | expect(constants.DEFAULT_CONFIG.canPublishReleases).toBeTruthy(); 58 | }); 59 | }); 60 | describe('INSTALLATION_EVENTS', () => { 61 | test('INSTALLATION_EVENTS has installation.created and installation_repositories events', () => { 62 | expect(constants.INSTALLATION_EVENTS).toBeDefined(); 63 | expect(Array.isArray(constants.INSTALLATION_EVENTS)).toBeTruthy(); 64 | expect(constants.INSTALLATION_EVENTS[0]).toEqual('installation.created'); 65 | expect(constants.INSTALLATION_EVENTS[1]).toEqual('installation_repositories'); 66 | }); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at abhijeetps@outlook.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /src/markdown/markdownBody.js: -------------------------------------------------------------------------------- 1 | 2 | const markdownIssues = require('./markdownIssues'); 3 | const markdownPullRequests = require('./markdownPullRequests'); 4 | const markdownContributors = require('./markdownContributors'); 5 | const markdownStargazers = require('./markdownStargazers'); 6 | const markdownCommits = require('./markdownCommits'); 7 | const markdownReleases = require('./markdownReleases'); 8 | 9 | const getAllIssues = require('../bin/getAllIssues'); 10 | const getAllPullRequests = require('../bin/getAllPullRequests'); 11 | const getStargazers = require('../bin/getStargazers'); 12 | const getCommits = require('../bin/getCommits'); 13 | const getReleases = require('../bin/getReleases'); 14 | 15 | module.exports = async (context, { 16 | owner, repo, headDate, tailDate, 17 | }, config) => { 18 | let body = `Here's the **Weekly Digest** for [*${owner}/${repo}*](https://github.com/${owner}/${repo}):\n`; 19 | let issuesString; 20 | let contributorsString; 21 | let pullRequestsString; 22 | let stargazersString; 23 | let commitsString; 24 | let releasesString; 25 | if (config.canPublishIssues) { 26 | const issues = await getAllIssues(context, { owner, repo, tailDate }); 27 | issuesString = markdownIssues(issues, headDate, tailDate); 28 | } 29 | if (config.canPublishPullRequests) { 30 | const pullRequests = await getAllPullRequests(context, { owner, repo }); 31 | pullRequestsString = markdownPullRequests(pullRequests, headDate, tailDate); 32 | } 33 | if (config.canPublishCommits || config.canPublishContributors) { 34 | const commits = await getCommits(context, { owner, repo, tailDate }); 35 | if (config.canPublishCommits) { 36 | commitsString = markdownCommits(commits, headDate, tailDate); 37 | } 38 | if (config.canPublishContributors) { 39 | contributorsString = markdownContributors(commits, headDate, tailDate); 40 | } 41 | } 42 | if (config.canPublishStargazers) { 43 | const stargazers = await getStargazers(context, { owner, repo }); 44 | stargazersString = markdownStargazers(stargazers, headDate, tailDate); 45 | } 46 | if (config.canPublishReleases) { 47 | const releases = await getReleases(context, { owner, repo }); 48 | releasesString = markdownReleases(releases, headDate, tailDate); 49 | } 50 | if (issuesString) { 51 | body += '\n - - - \n'; 52 | body += issuesString; 53 | } 54 | if (pullRequestsString) { 55 | body += '\n - - - \n'; 56 | body += pullRequestsString; 57 | } 58 | if (commitsString) { 59 | body += '\n - - - \n'; 60 | body += commitsString; 61 | } 62 | if (contributorsString) { 63 | body += '\n - - - \n'; 64 | body += contributorsString; 65 | } 66 | if (stargazersString) { 67 | body += '\n - - - \n'; 68 | body += stargazersString; 69 | } 70 | if (releasesString) { 71 | body += '\n - - - \n'; 72 | body += releasesString; 73 | } 74 | body += '\n - - - \n'; 75 | body += '\n'; 76 | body += `That's all for last week, please :eyes: **Watch** and :star: **Star** the repository [*${owner}/${repo}*](https://github.com/${owner}/${repo}) to receive next weekly updates. :smiley:\n\n`; 77 | body += `*You can also [view all Weekly Digests by clicking here](https://github.com/${owner}/${repo}/issues?q=is:open+is:issue+label:weekly-digest).* \n\n`; 78 | body += '> Your [**Weekly Digest**](https://github.com/apps/weekly-digest) bot. :calendar:\n'; 79 | context.log.debug(body); 80 | return body; 81 | }; 82 | -------------------------------------------------------------------------------- /src/markdown/markdownPullRequests.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = (pullRequests, headDate, tailDate) => { 5 | let pullRequestsString = '# PULL REQUESTS\n'; 6 | let data = pullRequests; 7 | if (!data) { 8 | data = []; 9 | } 10 | data = data.filter((item) => ( 11 | (moment(item.created_at).isBetween(tailDate, headDate) && item.state === 'open' && !item.merged_at && moment(item.created_at).isSame(item.updated_at) && item.user.login !== 'weekly-digest[bot]') 12 | || (moment(item.updated_at).isBetween(tailDate, headDate) && item.state === 'open' && !item.merged_at && item.user.login !== 'weekly-digest[bot]') 13 | || (moment(item.merged_at).isBetween(tailDate, headDate) && item.state === 'closed' && item.user.login !== 'weekly-digest[bot]') 14 | )); 15 | 16 | if (data.length === 0) { 17 | pullRequestsString += 'Last week, no pull requests were created, updated or merged.\n'; 18 | } else { 19 | pullRequestsString += `Last week, ${data.length} pull request${data.length > 1 ? 's were' : ' was'} created, updated or merged.\n`; 20 | const openPullRequest = data.filter((item) => (moment(item.created_at).isBetween(tailDate, headDate) && moment(item.created_at).isSame(item.updated_at) && !item.merged_at)); 21 | const updatedPullRequest = data.filter((item) => (moment(item.updated_at).isBetween(tailDate, headDate) && !moment(item.updated_at).isSame(item.created_at) && !item.merged_at)); 22 | const mergedPullRequest = data.filter((item) => (item.merged_at && moment(item.merged_at).isBetween(tailDate, headDate))); 23 | let mergedPullRequestString; 24 | let openPullRequestString; 25 | let updatedPullRequestString; 26 | if (mergedPullRequest.length > 0) { 27 | mergedPullRequestString = '## MERGED PULL REQUEST\n'; 28 | mergedPullRequestString += `Last week, ${mergedPullRequest.length} pull request${(mergedPullRequest.length > 1) ? 's were' : ' was'} merged.\n`; 29 | mergedPullRequest.forEach((item) => { 30 | mergedPullRequestString += `:purple_heart: #${item.number} [${item.title.replace(/\n/g, ' ')}](${item.html_url}), by [${item.user.login}](${item.user.html_url})\n`; 31 | }); 32 | } 33 | if (openPullRequest.length > 0) { 34 | openPullRequestString = '## OPEN PULL REQUEST\n'; 35 | openPullRequestString += `Last week, ${openPullRequest.length} pull request${(openPullRequest.length > 1) ? 's were' : ' was'} opened.\n`; 36 | openPullRequest.forEach((item) => { 37 | openPullRequestString += `:green_heart: #${item.number} [${item.title.replace(/\n/g, ' ')}](${item.html_url}), by [${item.user.login}](${item.user.html_url})\n`; 38 | }); 39 | } 40 | if (updatedPullRequest.length > 0) { 41 | updatedPullRequestString = '## UPDATED PULL REQUEST\n'; 42 | updatedPullRequestString += `Last week, ${updatedPullRequest.length} pull request${(updatedPullRequest.length > 1) ? 's were' : ' was'} updated.\n`; 43 | updatedPullRequest.forEach((item) => { 44 | updatedPullRequestString += `:yellow_heart: #${item.number} [${item.title.replace(/\n/g, ' ')}](${item.html_url}), by [${item.user.login}](${item.user.html_url})\n`; 45 | }); 46 | } 47 | if (typeof openPullRequestString !== 'undefined') { 48 | pullRequestsString += openPullRequestString; 49 | } 50 | if (typeof updatedPullRequestString !== 'undefined') { 51 | pullRequestsString += updatedPullRequestString; 52 | } 53 | if (typeof mergedPullRequestString !== 'undefined') { 54 | pullRequestsString += mergedPullRequestString; 55 | } 56 | } 57 | return pullRequestsString; 58 | }; 59 | -------------------------------------------------------------------------------- /test/markdown/markdownReleases.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownReleases = require('../../src/markdown/markdownReleases'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment().utc().format(); 8 | const tailDate = moment().utc().subtract(7, 'days').format(); 9 | 10 | const releases = require('../payload/releases'); 11 | 12 | const emptyReleases = releases.emptyReleases.data; 13 | const nullReleases = releases.nullReleases.data; 14 | const uselessReleases = releases.uselessReleases.data; 15 | const manyReleases = releases.manyReleases.data; 16 | const allReleases = releases.allReleases.data; 17 | const nullNameReleases = releases.nullNameReleases.data; 18 | 19 | test('that checks return string if the releases data is empty', () => { 20 | expect(markdownReleases(emptyReleases, headDate, tailDate)).toContain('# RELEASES'); 21 | expect(markdownReleases(emptyReleases, headDate, tailDate)).toContain('Last week there were no releases.'); 22 | }); 23 | 24 | test('that checks return string if the releases data is null', () => { 25 | expect(markdownReleases(nullReleases, headDate, tailDate)).toContain('# RELEASES'); 26 | expect(markdownReleases(nullReleases, headDate, tailDate)).toContain('Last week there were no releases.'); 27 | }); 28 | 29 | test('that checks return string if the releases data is useless', () => { 30 | expect(markdownReleases(uselessReleases, headDate, tailDate)).toContain('# RELEASES'); 31 | expect(markdownReleases(uselessReleases, headDate, tailDate)).toContain('Last week there were no releases.'); 32 | }); 33 | 34 | test('that checks return string if there are many releases', () => { 35 | expect(markdownReleases(manyReleases, headDate, tailDate)).toContain('# RELEASES'); 36 | expect(markdownReleases(manyReleases, headDate, tailDate)).toContain('Last week there were 3 releases.'); 37 | expect(markdownReleases(manyReleases, headDate, tailDate)).toContain(':rocket: [v1.0.0 Release v1.0.0](https://github.com/abhijeetps/playground/releases/tag/v1.0.0)'); 38 | expect(markdownReleases(manyReleases, headDate, tailDate)).toContain(':rocket: [v0.1.1 Release v0.1.1](https://github.com/abhijeetps/playground/releases/tag/v0.1.1)'); 39 | expect(markdownReleases(manyReleases, headDate, tailDate)).toContain(':rocket: [v0.0.1 Release v0.0.1](https://github.com/abhijeetps/playground/releases/tag/v0.0.1)'); 40 | }); 41 | 42 | test('that checks return string if there are some releases', () => { 43 | expect(markdownReleases(allReleases, headDate, tailDate)).toContain('# RELEASES'); 44 | expect(markdownReleases(allReleases, headDate, tailDate)).toContain('Last week there was 1 release.'); 45 | expect(markdownReleases(allReleases, headDate, tailDate)).toContain(':rocket: [v0.1.1 Release v0.1.1](https://github.com/abhijeetps/playground/releases/tag/v0.1.1)'); 46 | }); 47 | 48 | test('that checks return string if there are some releases where name is null', () => { 49 | expect(markdownReleases(allReleases, headDate, tailDate)).toContain('# RELEASES'); 50 | expect(markdownReleases(allReleases, headDate, tailDate)).toContain('Last week there was 1 release.'); 51 | expect(markdownReleases(allReleases, headDate, tailDate)).toContain(':rocket: [v0.1.1 Release v0.1.1](https://github.com/abhijeetps/playground/releases/tag/v0.1.1)'); 52 | }); 53 | 54 | test('that checks return string if there are some releases where name is null', () => { 55 | expect(markdownReleases(nullNameReleases, headDate, tailDate)).toContain('# RELEASES'); 56 | expect(markdownReleases(nullNameReleases, headDate, tailDate)).toContain('Last week there was 1 release.'); 57 | expect(markdownReleases(nullNameReleases, headDate, tailDate)).toContain(':rocket: [v0.1.1](https://github.com/abhijeetps/playground/releases/tag/v0.1.1)'); 58 | }); 59 | -------------------------------------------------------------------------------- /src/markdown/markdownIssues.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | 4 | module.exports = (issues, headDate, tailDate) => { 5 | let issuesString = '# ISSUES\n'; 6 | let data = issues; 7 | if (!data) { 8 | data = []; 9 | } 10 | data = data.filter((item) => { 11 | if (moment(item.created_at).isBetween(tailDate, headDate) && (item.user.login !== 'weekly-digest[bot]')) { 12 | return true; 13 | } 14 | return false; 15 | }); 16 | if (data.length === 0) { 17 | issuesString += 'Last week, no issues were created.\n'; 18 | } else { 19 | let openIssueString; 20 | let closedIssueString; 21 | let likedIssueString; 22 | let noisyIssueString; 23 | if (data.length === 1) { 24 | issuesString += `Last week ${data.length} issue was created.\n`; 25 | } else { 26 | issuesString += `Last week ${data.length} issues were created.\n`; 27 | } 28 | const openIssue = data.filter((item) => item.state === 'open'); 29 | if (openIssue.length > 0) { 30 | openIssueString = '## OPEN ISSUES\n'; 31 | } 32 | const closedIssue = data.filter((item) => item.state === 'closed'); 33 | if (closedIssue.length > 0) { 34 | closedIssueString = '## CLOSED ISSUES\n'; 35 | } 36 | if (data.length === 1 && openIssue.length === 1) { 37 | issuesString += 'It is still open.\n'; 38 | } else if (data.length === 1 && closedIssue.length === 1) { 39 | issuesString += 'It is closed now.\n'; 40 | } else { 41 | issuesString += `Of these, ${closedIssue.length} issues have been closed and ${openIssue.length} issues are still open.\n`; 42 | } 43 | openIssue.forEach((item) => { 44 | openIssueString += `:green_heart: #${item.number} [${item.title.replace(/\n/g, ' ')}](${item.html_url}), by [${item.user.login}](${item.user.html_url})\n`; 45 | }); 46 | closedIssue.forEach((item) => { 47 | closedIssueString += `:heart: #${item.number} [${item.title.replace(/\n/g, ' ')}](${item.html_url}), by [${item.user.login}](${item.user.html_url})\n`; 48 | }); 49 | if (openIssueString) { 50 | issuesString += openIssueString; 51 | } 52 | if (closedIssueString) { 53 | issuesString += closedIssueString; 54 | } 55 | // To get the most recent liked or noisy issue 56 | data.reverse(); 57 | // For Liked issue 58 | const likedIssue = data.filter((item) => (item.reactions['+1'] + item.reactions.laugh + item.reactions.hooray + item.reactions.heart) > 0); 59 | if (likedIssue.length > 0) { 60 | likedIssueString = '## LIKED ISSUE\n'; 61 | let likedIssueItem = likedIssue[0]; 62 | likedIssue.forEach((item) => { 63 | if ((item.reactions['+1'] + item.reactions.laugh + item.reactions.hooray + item.reactions.heart) > (likedIssueItem.reactions['+1'] + likedIssueItem.reactions.laugh + likedIssueItem.reactions.hooray + likedIssueItem.reactions.heart)) { 64 | likedIssueItem = item; 65 | } 66 | }); 67 | likedIssueString += `:+1: #${likedIssueItem.number} [${likedIssueItem.title.replace(/\n/g, ' ')}](${likedIssueItem.html_url}), by [${likedIssueItem.user.login}](${likedIssueItem.user.html_url})\n`; 68 | likedIssueString += `It received :+1: x${likedIssueItem.reactions['+1']}, :smile: x${likedIssueItem.reactions.laugh}, :tada: x${likedIssueItem.reactions.hooray} and :heart: x${likedIssueItem.reactions.heart}.\n`; 69 | } 70 | if (likedIssueString) { 71 | issuesString += likedIssueString; 72 | } 73 | // For Noisy issue 74 | const noisyIssue = data.filter((item) => (item.comments > 0)); 75 | if (noisyIssue.length > 0) { 76 | noisyIssueString = '## NOISY ISSUE\n'; 77 | let noisyIssueItem = noisyIssue[0]; 78 | noisyIssue.forEach((item) => { 79 | if ((item.comments) > (noisyIssueItem.comments)) { 80 | noisyIssueItem = item; 81 | } 82 | }); 83 | noisyIssueString += `:speaker: #${noisyIssueItem.number} [${noisyIssueItem.title.replace(/\n/g, ' ')}](${noisyIssueItem.html_url}), by [${noisyIssueItem.user.login}](${noisyIssueItem.user.html_url})\n`; 84 | noisyIssueString += `It received ${noisyIssueItem.comments} comments.\n`; 85 | } 86 | if (noisyIssueString) { 87 | issuesString += noisyIssueString; 88 | } 89 | } 90 | return issuesString; 91 | }; 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Weekly Digest 3 | 4 | > App built using [Probot](https://probot.github.io/) which generates a weekly automated summary of activities and happening on your GitHub repository. 5 | 6 |

Weekly Digest Logo

7 |

8 | Installs 9 | Uptime Robot status 10 | Build Status 11 |

12 | 13 | 14 | ## App in Action 15 | 16 | ![A Weekly Digest generated by app.](https://user-images.githubusercontent.com/20141002/41304450-d2bc9234-6e8d-11e8-965d-649ed2d04651.gif) 17 | 18 | ## Installation 19 | 20 | 1. Explore Weekly Digest app here: [GitHub Apps - Weekly Digest](https://github.com/apps/weekly-digest) 21 | 2. Now, click install and confim your installation location. 22 | 3. Your app is ready and is live, visit your repository to check out the weekly digest the app has published! 23 | 24 | ## Features 25 | 26 | When the Weekly Digest App gets installed in a repository of a user or organization, it curates together the following data and publishes it as an issue: 27 | 28 | - Issues created in the last one week 29 | - Open Issues 30 | - Closed Issues 31 | - Noisy Issue 32 | - Liked Issue 33 | - Pull requests opened, updated, or merged in the last pull request 34 | - Opened Pull Requests 35 | - Updated Pull Requests 36 | - Merged Pull Requests 37 | - Commits made in the master branch, in the last week 38 | - Contributors, adding contributions in the last week 39 | - Stargazers, or the fans of your repositories, who really loved your repo 40 | - Releases, of the project you are working on 41 | 42 | The app, as the name suggests, generates these digests and publishes it on weekly basis, typically on a Sunday. 43 | 44 | One can change the default configuration of the app by adding a [_.github/weekly-digest.yml_](docs/configuration.md) file in their GitHub repository, which allows them to configure the publication day and the specific information included in the digest. 45 | 46 | ## How to Contribute 47 | 1. Fork this repository. 48 | 2. Clone the forked repository on your development machine. 49 | 3. Move into your project's directory: `cd weekly-digest` 50 | 4. Run `npm install` to setup the project. 51 | 5. Follow [Configuring a GitHub App](https://probot.github.io/docs/development/#configuring-a-github-app) too configure your app on your development machine. 52 | 6. Follow [Running the app locally](https://probot.github.io/docs/development/#running-the-app-locally) to run your app on your development machine. 53 | 7. Before you add a feature or suggest some changes, we recommend [opening an issue here](https://github.com/probot/weekly-digest/issues/new) so that we can have a discussion about the changes. 54 | 8. Please make sure you run `npm test` before submitting a pull request. If possible, please add tests for your changes also. 55 | 56 | ## Code Style 57 | The app is using [Javascript Standard Style](https://standardjs.com/) for linting. 58 | 59 | ## Test Framework 60 | The app is using [Jest](https://jestjs.io/) for Javascript testing. 61 | 62 | ## Credits 63 | This project is developed and maintained by [Abhijeet Singh](https://github.com/abhijeetps). 64 | 65 | It is one of the [Google Summer of Code 2018](https://summerofcode.withgoogle.com/) Projects. 66 | 67 | [Click here to view this Project \"Weekly Digest\" on Google Summer of Code 2018 Projects](https://summerofcode.withgoogle.com/projects/#5611987044663296) 68 | 69 | I would like to thanks [Gregor Martynus](https://github.com/gr2m) and [Wilhelm Klopp](https://github.com/wilhelmklopp) for being really awesome mentors and guiding me for this project. :heart: 70 | -------------------------------------------------------------------------------- /docs/GSoC.md: -------------------------------------------------------------------------------- 1 | # Google Summer of Code Final Report 2 | 3 | This Google Summer of Code (GSoC), I worked with organization Probot, which delivers a framework that is used to build applications for GitHub. 4 | 5 | Here, I developed the Weekly Digest application for GitHub, which generates a weekly summary of activity on your GitHub repository. 6 | 7 | ## The Problem 8 | 9 | GitHub is a very popular web-based hosting service for version control using Git. 10 | 11 | As per the statistics provided in the [GitHub Octoverse 2017](https://octoverse.github.com/), there are 24 million total users, 1.5 million total organizations and 67 million total repositories on GitHub. 12 | 13 | It’s a huge count of the number of users and organizations. 14 | 15 | There have been 1.0 billion commits in last year, along with 25.3 million active repositories, 12.5 million active issues and 47 million public and private pull requests merged. 16 | 17 | Also, since September 2016, around 6.7 million developers have joined Github, 451 thousand new organizations have been created with around 1.2 million people making their first pull request and 191 thousand people staring or forking a repository without pushing code. 18 | 19 | These figures are really huge and we can conclude that most of the Open Source is hosted on GitHub today. 20 | 21 | Many of these activities, which are really significant to the users contributing in the organization or a repository goes unnoticed. 22 | 23 | Currently, there is no way by which maintainers can generate a report and summarize details of the numbers of public commits, active issues, pull requests or comments on issues and other useful data. 24 | 25 | There are many organizations which generate a weekly report of all the events occurring in their organizations. However, their weekly reports or weekly digests are manually generated or are generated by external bots, and these bots are only organization depended and they need to be configured per organization or per-repository basis. Also, these external bots are not First Actors in GitHub. 26 | 27 | It can be seen that users or organizations are highly interested in maintaining a weekly digest for their repository, however, due to the lack of an application, which does this task, they have to do it manually or using some external application. 28 | 29 | ## The Solution 30 | 31 | To solve this problem, I developed the Weekly Digest app based on Probot Framework which generates a weekly automated summary of activity on your GitHub repository. 32 | 33 | The app listens to [Github Webhook Events](https://developer.github.com/webhooks/#events) like `installation.created` and `installation_repositories`, and also to `schedule.repository` which are the GitHub events that trigger the application. 34 | 35 | The app then reads the configuration of the application (if it's available) and checks the details that it has to publish using [probot-config](https://www.npmjs.com/package/probot-config). 36 | 37 | Then the application gets details like issues, pull requests, commits, contributors, stargazers and releases for the repositories (Using [Octokit REST APIs](https://octokit.github.io/rest.js/)) and adds [GitHub Markdown](https://guides.github.com/features/mastering-markdown/) to it. 38 | 39 | Finally, the application publishes the fetched details an issue and adds _weekly-digest_ label to it. This is repeated every week, by default on Sunday. 40 | 41 | ### So, what is the app doing? 42 | 43 | When the Weekly Digest App gets installed in a repository of a user or organization, it curates together the following data and publishes it as an issue: 44 | 45 | - Issues created in the last one week 46 | - Open Issues 47 | - Closed Issues 48 | - Noisy Issue 49 | - Liked Issue 50 | - Pull requests opened, updated, or merged in the last pull request 51 | - Opened Pull Requests 52 | - Updated Pull Requests 53 | - Merged Pull Requests 54 | - Commits made in the master branch, in the last week 55 | - Contributors, adding contributions in the last week 56 | - Stargazers, or the fans of your repositories, who really loved your repo 57 | - Releases, of the project you are working on 58 | 59 | The app, as the name suggests, generates these digests and publishes it on weekly basis, typically on a Sunday. 60 | 61 | One can change the default configuration of the app by adding a _.github/weekly-digest.yml_ file in their GitHub repository, which allows them to configure the publish day and the specific information included in the digest. 62 | 63 | ## What I learned? 64 | This summer, I learned how to create and maintain an Open Source project. This is the most basic thing that I learned this summer. 65 | 66 | Apart from this, I learned how to develop applications for GitHub using GitHub v3 APIs and Octokit REST APIs, everything in the node environment. I also learned some advanced programming concepts of NodeJS and JavaScript. 67 | 68 | The most challenging part for me was writing tests for my app using Jest. This is something that I have never done before and it was the most challenging part for me. 69 | 70 | Thus, I was able to develop and maintain a webhook triggered Github app which publishes the weekly digest in an issue in a locked repository. 71 | 72 | ## What could be done more? 73 | - Publishing weekly digests of Orgs and Users in a single public repository 74 | - Autoclosing old and stale issues labeled _weekly-digest_ 75 | - Adding more features and activities that could be published in the Weekly Digest 76 | 77 | ## Useful Links 78 | - App URL: [Github Apps - Weekly Digest](https://github.com/apps/weekly-digest) 79 | - Project URL: [probot/weekly-digest](https://github.com/probot/weekly-digest) 80 | - Weekly Digest App on Probot: [Weekly Digest | Probot](https://probot.github.io/apps/weekly-digest/) 81 | - [README.md](https://github.com/probot/weekly-digest/blob/master/README.md) 82 | - [My Commits](https://github.com/probot/weekly-digest/commits/master) (**Note: I have changed my username from aps120797 to abhijeetps. Commits made by the user "aps120797" and "Abhijeet Singh" are made by me only**) 83 | -------------------------------------------------------------------------------- /test/payload/commits.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | emptyCommits: { 3 | data: [], 4 | }, 5 | nullCommits: { 6 | data: null, 7 | }, 8 | uselessCommits: { 9 | data: [ 10 | { 11 | commit: 12 | { 13 | message: 'Weekly-Digest commit test6', 14 | committer: { 15 | date: '2018-04-24T00:00:00Z', 16 | }, 17 | }, 18 | author: 19 | { 20 | login: 'weekly-digest[bot]', 21 | html_url: 'https://github.com/apps/weekly-digest', 22 | }, 23 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-6', 24 | }, 25 | { 26 | commit: 27 | { 28 | message: 'Weekly-Digest commit test5', 29 | committer: { 30 | date: '2018-04-24T00:00:00Z', 31 | }, 32 | }, 33 | author: 34 | { 35 | login: 'abhijeetps', 36 | html_url: 'https://github.com/abhijeetps/', 37 | }, 38 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-5', 39 | }, 40 | { 41 | commit: 42 | { 43 | message: 'Weekly-Digest commit test4', 44 | committer: { 45 | date: '2018-04-20T00:00:00Z', 46 | }, 47 | }, 48 | author: 49 | { 50 | login: 'weekly-digest[bot]', 51 | html_url: 'https://github.com/app/weekly-digest', 52 | }, 53 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-4', 54 | }, 55 | { 56 | commit: 57 | { 58 | message: 'Weekly-Digest commit test2', 59 | committer: { 60 | date: '2018-04-16T00:00:00Z', 61 | }, 62 | }, 63 | author: 64 | { 65 | login: 'weekly-digest[bot]', 66 | html_url: 'https://github.com/apps/weekly-digest', 67 | }, 68 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-2', 69 | }, 70 | { 71 | commit: 72 | { 73 | message: 'Weekly-Digest commit test1', 74 | committer: { 75 | date: '2018-04-16T00:00:00Z', 76 | }, 77 | }, 78 | author: 79 | { 80 | login: 'abhijeetps', 81 | html_url: 'https://github.com/abhijeetps/', 82 | }, 83 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-1', 84 | }, 85 | ], 86 | }, 87 | manyCommits: { 88 | data: [ 89 | { 90 | commit: 91 | { 92 | message: 'Weekly-Digest commit test3', 93 | committer: { 94 | date: '2018-04-20T00:00:00Z', 95 | }, 96 | }, 97 | author: 98 | { 99 | login: 'gr2m', 100 | html_url: 'https://github.com/gr2m/', 101 | }, 102 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-3', 103 | }, 104 | { 105 | commit: 106 | { 107 | message: 'Weekly-Digest commit test3', 108 | committer: { 109 | date: '2018-04-20T00:00:00Z', 110 | }, 111 | }, 112 | author: 113 | { 114 | login: 'wilhelmklopp', 115 | html_url: 'https://github.com/wilhelmklopp/', 116 | }, 117 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-2', 118 | }, 119 | { 120 | commit: 121 | { 122 | message: 'Weekly-Digest commit test3', 123 | committer: { 124 | date: '2018-04-20T00:00:00Z', 125 | }, 126 | }, 127 | author: 128 | { 129 | login: 'abhijeetps', 130 | html_url: 'https://github.com/abhijeetps/', 131 | }, 132 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-1', 133 | }, 134 | ], 135 | }, 136 | allCommits: { 137 | data: [ 138 | { 139 | commit: 140 | { 141 | message: 'Weekly-Digest commit test6', 142 | committer: { 143 | date: '2018-04-24T00:00:00Z', 144 | }, 145 | }, 146 | author: 147 | { 148 | login: 'weekly-digest[bot]', 149 | html_url: 'https://github.com/apps/weekly-digest', 150 | }, 151 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-6', 152 | }, 153 | { 154 | commit: 155 | { 156 | message: 'Weekly-Digest commit test5', 157 | committer: { 158 | date: '2018-04-24T00:00:00Z', 159 | }, 160 | }, 161 | author: 162 | { 163 | login: 'abhijeetps', 164 | html_url: 'https://github.com/abhijeetps/', 165 | }, 166 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-5', 167 | }, 168 | { 169 | commit: 170 | { 171 | message: 'Weekly-Digest commit test4', 172 | committer: { 173 | date: '2018-04-20T00:00:00Z', 174 | }, 175 | }, 176 | author: 177 | { 178 | login: 'weekly-digest[bot]', 179 | html_url: 'https://github.com/app/weekly-digest', 180 | }, 181 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-4', 182 | }, 183 | { 184 | commit: 185 | { 186 | message: 'Weekly-Digest commit test3', 187 | committer: { 188 | date: '2018-04-20T00:00:00Z', 189 | }, 190 | }, 191 | author: 192 | { 193 | login: 'abhijeetps', 194 | html_url: 'https://github.com/abhijeetps/', 195 | }, 196 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-3', 197 | }, 198 | { 199 | commit: 200 | { 201 | message: 'Weekly-Digest commit test2', 202 | committer: { 203 | date: '2018-04-16T00:00:00Z', 204 | }, 205 | }, 206 | author: 207 | { 208 | login: 'weekly-digest[bot]', 209 | html_url: 'https://github.com/apps/weekly-digest', 210 | }, 211 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-2', 212 | }, 213 | { 214 | commit: 215 | { 216 | message: 'Weekly-Digest commit test1', 217 | committer: { 218 | date: '2018-04-16T00:00:00Z', 219 | }, 220 | }, 221 | author: 222 | { 223 | login: 'abhijeetps', 224 | html_url: 'https://github.com/abhijeetps/', 225 | }, 226 | html_url: 'https://github.com/abhijeetps/playground/commit/commit-sha-1', 227 | }, 228 | ], 229 | }, 230 | }; 231 | -------------------------------------------------------------------------------- /test/markdown/markdownPullRequests.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownPullRequests = require('../../src/markdown/markdownPullRequests'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment().utc().format(); 8 | const tailDate = moment().utc().subtract(7, 'days').format(); 9 | 10 | const pullRequests = require('../payload/pullRequests'); 11 | 12 | const emptyPullRequest = pullRequests.emptyPullRequest.data; 13 | const nullPullRequest = pullRequests.nullPullRequest.data; 14 | const uselessPullRequest = pullRequests.uselessPullRequest.data; 15 | const mergedPullRequest = pullRequests.mergedPullRequest.data; 16 | const openPullRequest = pullRequests.openPullRequest.data; 17 | const updatedPullRequest = pullRequests.updatedPullRequest.data; 18 | const allPullRequest = pullRequests.allPullRequests.data; 19 | const onePullRequest = pullRequests.onePullRequest.data; 20 | 21 | test('that checks return string if the pull requests is empty', () => { 22 | expect(markdownPullRequests(emptyPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 23 | expect(markdownPullRequests(emptyPullRequest, headDate, tailDate)).toContain('Last week, no pull requests were created, updated or merged.'); 24 | }); 25 | 26 | test('that checks return string if the pull requests is null', () => { 27 | expect(markdownPullRequests(nullPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 28 | expect(markdownPullRequests(nullPullRequest, headDate, tailDate)).toContain('Last week, no pull requests were created, updated or merged.'); 29 | }); 30 | 31 | test('that checks return string if the pull requests are useless', () => { 32 | expect(markdownPullRequests(uselessPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 33 | expect(markdownPullRequests(uselessPullRequest, headDate, tailDate)).toContain('Last week, no pull requests were created, updated or merged.'); 34 | }); 35 | 36 | test('that checks return string if there is one pull request', () => { 37 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 38 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were created, updated or merged.'); 39 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('## OPEN PULL REQUEST'); 40 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were opened.'); 41 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain(':green_heart: #15 [Weekly Digest test15](https://github.com/abhijeetps/playground/pull/15), by [abhijeetps](https://github.com/abhijeetps)'); 42 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain(':green_heart: #14 [Weekly Digest test14](https://github.com/abhijeetps/playground/pull/14), by [abhijeetps](https://github.com/abhijeetps)'); 43 | }); 44 | 45 | test('that checks return string if there are open pull requests', () => { 46 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 47 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were created, updated or merged.'); 48 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('## OPEN PULL REQUEST'); 49 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were opened.'); 50 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain(':green_heart: #15 [Weekly Digest test15](https://github.com/abhijeetps/playground/pull/15), by [abhijeetps](https://github.com/abhijeetps)'); 51 | expect(markdownPullRequests(openPullRequest, headDate, tailDate)).toContain(':green_heart: #14 [Weekly Digest test14](https://github.com/abhijeetps/playground/pull/14), by [abhijeetps](https://github.com/abhijeetps)'); 52 | }); 53 | 54 | test('that checks return string if there are updated pull requests', () => { 55 | expect(markdownPullRequests(updatedPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 56 | expect(markdownPullRequests(updatedPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were created, updated or merged.'); 57 | expect(markdownPullRequests(updatedPullRequest, headDate, tailDate)).toContain('## UPDATED PULL REQUEST'); 58 | expect(markdownPullRequests(updatedPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were updated.'); 59 | expect(markdownPullRequests(updatedPullRequest, headDate, tailDate)).toContain(':yellow_heart: #17 [Weekly Digest test17](https://github.com/abhijeetps/playground/pull/17), by [abhijeetps](https://github.com/abhijeetps)'); 60 | expect(markdownPullRequests(updatedPullRequest, headDate, tailDate)).toContain(':yellow_heart: #16 [Weekly Digest test16](https://github.com/abhijeetps/playground/pull/16), by [abhijeetps](https://github.com/abhijeetps)'); 61 | }); 62 | 63 | test('that checks return string if there are merged pull requests', () => { 64 | expect(markdownPullRequests(mergedPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 65 | expect(markdownPullRequests(mergedPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were created, updated or merged.'); 66 | expect(markdownPullRequests(mergedPullRequest, headDate, tailDate)).toContain('## MERGED PULL REQUEST'); 67 | expect(markdownPullRequests(mergedPullRequest, headDate, tailDate)).toContain('Last week, 2 pull requests were merged.'); 68 | expect(markdownPullRequests(mergedPullRequest, headDate, tailDate)).toContain(':purple_heart: #25 [Weekly Digest test25](https://github.com/abhijeetps/playground/pull/25), by [abhijeetps](https://github.com/abhijeetps)'); 69 | expect(markdownPullRequests(mergedPullRequest, headDate, tailDate)).toContain(':purple_heart: #24 [Weekly Digest test24](https://github.com/abhijeetps/playground/pull/24), by [abhijeetps](https://github.com/abhijeetps)'); 70 | }); 71 | 72 | test('that checks return string if there are some pull requests', () => { 73 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 74 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('Last week, 3 pull requests were created, updated or merged.'); 75 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('## OPEN PULL REQUEST'); 76 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('Last week, 1 pull request was opened.'); 77 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain(':green_heart: #14 [Weekly Digest test14](https://github.com/abhijeetps/playground/pull/14), by [abhijeetps](https://github.com/abhijeetps)'); 78 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('## UPDATED PULL REQUEST'); 79 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('Last week, 1 pull request was updated.'); 80 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain(':yellow_heart: #16 [Weekly Digest test16](https://github.com/abhijeetps/playground/pull/16), by [abhijeetps](https://github.com/abhijeetps)'); 81 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('## MERGED PULL REQUEST'); 82 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain('Last week, 1 pull request was merged.'); 83 | expect(markdownPullRequests(allPullRequest, headDate, tailDate)).toContain(':purple_heart: #24 [Weekly Digest test24](https://github.com/abhijeetps/playground/pull/24), by [abhijeetps](https://github.com/abhijeetps)'); 84 | }); 85 | 86 | test('that checks return string if the pull requests is null', () => { 87 | expect(markdownPullRequests(onePullRequest, headDate, tailDate)).toContain('# PULL REQUESTS'); 88 | expect(markdownPullRequests(onePullRequest, headDate, tailDate)).toContain('Last week, 1 pull request was created, updated or merged.'); 89 | expect(markdownPullRequests(onePullRequest, headDate, tailDate)).toContain('## OPEN PULL REQUEST'); 90 | expect(markdownPullRequests(onePullRequest, headDate, tailDate)).toContain('Last week, 1 pull request was opened.'); 91 | expect(markdownPullRequests(onePullRequest, headDate, tailDate)).toContain(':green_heart: #14 [Weekly Digest test14](https://github.com/abhijeetps/playground/pull/14), by [abhijeetps](https://github.com/abhijeetps)'); 92 | }); 93 | -------------------------------------------------------------------------------- /test/markdown/markdownIssues.test.js: -------------------------------------------------------------------------------- 1 | 2 | const moment = require('moment'); 3 | const MockDate = require('mockdate'); 4 | const markdownIssues = require('../../src/markdown/markdownIssues'); 5 | 6 | MockDate.set(moment.utc('2018-04-24')); 7 | const headDate = moment().utc().format(); 8 | const tailDate = moment().utc().subtract(7, 'days').format(); 9 | 10 | const issues = require('../payload/issues'); 11 | 12 | const nullIssue = issues.nullIssue.data; 13 | const emptyIssue = issues.emptyIssue.data; 14 | const openIssue = issues.openIssue.data; 15 | const closedIssue = issues.closedIssue.data; 16 | const uselessIssue = issues.uselessIssue.data; 17 | const likedIssue = issues.likedIssue.data; 18 | const noisyIssue = issues.noisyIssue.data; 19 | const allIssueA = issues.allIssueA.data; 20 | const allIssueB = issues.allIssueB.data; 21 | 22 | test('that checks return string if payload is null', () => { 23 | expect(markdownIssues(nullIssue, headDate, tailDate)).toContain('# ISSUES'); 24 | expect(markdownIssues(nullIssue, headDate, tailDate)).toContain('Last week, no issues were created.'); 25 | }); 26 | 27 | test('that checks return string if payload is empty', () => { 28 | expect(markdownIssues(emptyIssue, headDate, tailDate)).toContain('# ISSUES'); 29 | expect(markdownIssues(emptyIssue, headDate, tailDate)).toContain('Last week, no issues were created.'); 30 | }); 31 | 32 | test('that checks return string if all the issues are useless', () => { 33 | expect(markdownIssues(uselessIssue, headDate, tailDate)).toContain('# ISSUES'); 34 | expect(markdownIssues(uselessIssue, headDate, tailDate)).toContain('Last week, no issues were created.'); 35 | }); 36 | 37 | test('that checks return string if payload has only one data - closed issue', () => { 38 | expect(markdownIssues(closedIssue, headDate, tailDate)).toContain('# ISSUES'); 39 | expect(markdownIssues(closedIssue, headDate, tailDate)).toContain('Last week 1 issue was created.'); 40 | expect(markdownIssues(closedIssue, headDate, tailDate)).toContain('It is closed now.'); 41 | expect(markdownIssues(closedIssue, headDate, tailDate)).toContain('## CLOSED ISSUES'); 42 | expect(markdownIssues(closedIssue, headDate, tailDate)).toContain(':heart: #4 [Weekly Digest test4](https://github.com/abhijeetps/playground/issues/4), by [abhijeetps](https://github.com/abhijeetps)'); 43 | }); 44 | 45 | test('that checks return string if payload has only one data - open issue', () => { 46 | expect(markdownIssues(openIssue, headDate, tailDate)).toContain('# ISSUES'); 47 | expect(markdownIssues(openIssue, headDate, tailDate)).toContain('Last week 1 issue was created.'); 48 | expect(markdownIssues(openIssue, headDate, tailDate)).toContain('It is still open.'); 49 | expect(markdownIssues(openIssue, headDate, tailDate)).toContain('## OPEN ISSUES'); 50 | expect(markdownIssues(openIssue, headDate, tailDate)).toContain(':green_heart: #4 [Weekly Digest test4](https://github.com/abhijeetps/playground/issues/4), by [abhijeetps](https://github.com/abhijeetps)'); 51 | }); 52 | 53 | test('that checks return string to test noisy issues', () => { 54 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('# ISSUES'); 55 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('Last week 2 issues were created.'); 56 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('Of these, 1 issues have been closed and 1 issues are still open.'); 57 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('## OPEN ISSUES'); 58 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain(':green_heart: #5 [Weekly Digest test5](https://github.com/abhijeetps/playground/issues/5), by [abhijeetps](https://github.com/abhijeetps)'); 59 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('## CLOSED ISSUES'); 60 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain(':heart: #4 [Weekly Digest test4](https://github.com/abhijeetps/playground/issues/4), by [abhijeetps](https://github.com/abhijeetps)'); 61 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('## NOISY ISSUE'); 62 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain(':speaker: #4 [Weekly Digest test4](https://github.com/abhijeetps/playground/issues/4), by [abhijeetps](https://github.com/abhijeetps)'); 63 | expect(markdownIssues(noisyIssue, headDate, tailDate)).toContain('It received 7 comments.'); 64 | }); 65 | 66 | test('that checks return string to test liked issues', () => { 67 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('# ISSUES'); 68 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('Last week 2 issues were created.'); 69 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('Of these, 1 issues have been closed and 1 issues are still open.'); 70 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('## OPEN ISSUES'); 71 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain(':green_heart: #5 [Weekly Digest test5](https://github.com/abhijeetps/playground/issues/5), by [abhijeetps](https://github.com/abhijeetps)'); 72 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('## CLOSED ISSUES'); 73 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain(':heart: #4 [Weekly Digest test4](https://github.com/abhijeetps/playground/issues/4), by [abhijeetps](https://github.com/abhijeetps)'); 74 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('## LIKED ISSUE'); 75 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain(':+1: #4 [Weekly Digest test4](https://github.com/abhijeetps/playground/issues/4), by [abhijeetps](https://github.com/abhijeetps)'); 76 | expect(markdownIssues(likedIssue, headDate, tailDate)).toContain('It received :+1: x3, :smile: x2, :tada: x5 and :heart: x2.'); 77 | }); 78 | 79 | test('that checks return string if payload has some data A', () => { 80 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('# ISSUES'); 81 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('Last week 2 issues were created.'); 82 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('Of these, 1 issues have been closed and 1 issues are still open.'); 83 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('## OPEN ISSUES'); 84 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain(':green_heart: #6 [Weekly Digest test6](https://github.com/abhijeetps/playground/issues/6), by [abhijeetps](https://github.com/abhijeetps)'); 85 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('## CLOSED ISSUES'); 86 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain(':heart: #5 [Weekly Digest test5](https://github.com/abhijeetps/playground/issues/5), by [abhijeetps](https://github.com/abhijeetps)'); 87 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('## LIKED ISSUE'); 88 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain(':+1: #5 [Weekly Digest test5](https://github.com/abhijeetps/playground/issues/5), by [abhijeetps](https://github.com/abhijeetps)'); 89 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('It received :+1: x2, :smile: x3, :tada: x1 and :heart: x2.'); 90 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('## NOISY ISSUE'); 91 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain(':speaker: #6 [Weekly Digest test6](https://github.com/abhijeetps/playground/issues/6), by [abhijeetps](https://github.com/abhijeetps)'); 92 | expect(markdownIssues(allIssueA, headDate, tailDate)).toContain('It received 6 comments.'); 93 | }); 94 | 95 | test('that checks return string if payload has some data B', () => { 96 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('# ISSUES'); 97 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('Last week 2 issues were created.'); 98 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('Of these, 1 issues have been closed and 1 issues are still open.'); 99 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('## OPEN ISSUES'); 100 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain(':green_heart: #6 [Weekly Digest test6](https://github.com/abhijeetps/playground/issues/6), by [abhijeetps](https://github.com/abhijeetps)'); 101 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('## CLOSED ISSUES'); 102 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain(':heart: #5 [Weekly Digest test5](https://github.com/abhijeetps/playground/issues/5), by [abhijeetps](https://github.com/abhijeetps)'); 103 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('## LIKED ISSUE'); 104 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain(':+1: #6 [Weekly Digest test6](https://github.com/abhijeetps/playground/issues/6), by [abhijeetps](https://github.com/abhijeetps)'); 105 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('It received :+1: x2, :smile: x3, :tada: x1 and :heart: x2.'); 106 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('## NOISY ISSUE'); 107 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain(':speaker: #5 [Weekly Digest test5](https://github.com/abhijeetps/playground/issues/5), by [abhijeetps](https://github.com/abhijeetps)'); 108 | expect(markdownIssues(allIssueB, headDate, tailDate)).toContain('It received 6 comments.'); 109 | }); 110 | -------------------------------------------------------------------------------- /test/payload/issues.opened.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "opened", 3 | "issue": { 4 | "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", 5 | "repository_url": "https://api.github.com/repos/Codertocat/Hello-World", 6 | "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/labels{/name}", 7 | "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/comments", 8 | "events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/events", 9 | "html_url": "https://github.com/Codertocat/Hello-World/issues/2", 10 | "id": 327883527, 11 | "node_id": "MDU6SXNzdWUzMjc4ODM1Mjc=", 12 | "number": 2, 13 | "title": "Spelling error in the README file", 14 | "user": { 15 | "login": "Codertocat", 16 | "id": 21031067, 17 | "node_id": "MDQ6VXNlcjIxMDMxMDY3", 18 | "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", 19 | "gravatar_id": "", 20 | "url": "https://api.github.com/users/Codertocat", 21 | "html_url": "https://github.com/Codertocat", 22 | "followers_url": "https://api.github.com/users/Codertocat/followers", 23 | "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", 24 | "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", 25 | "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", 26 | "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", 27 | "organizations_url": "https://api.github.com/users/Codertocat/orgs", 28 | "repos_url": "https://api.github.com/users/Codertocat/repos", 29 | "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", 30 | "received_events_url": "https://api.github.com/users/Codertocat/received_events", 31 | "type": "User", 32 | "site_admin": false 33 | }, 34 | "state": "open", 35 | "locked": false, 36 | "assignee": null, 37 | "assignees": [], 38 | "milestone": null, 39 | "comments": 0, 40 | "created_at": "2018-05-30T20:18:32Z", 41 | "updated_at": "2018-05-30T20:18:32Z", 42 | "closed_at": null, 43 | "author_association": "OWNER", 44 | "body": "It looks like you accidently spelled 'commit' with two 't's." 45 | }, 46 | "repository": { 47 | "id": 135493233, 48 | "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=", 49 | "name": "Hello-World", 50 | "full_name": "Codertocat/Hello-World", 51 | "owner": { 52 | "login": "Codertocat", 53 | "id": 21031067, 54 | "node_id": "MDQ6VXNlcjIxMDMxMDY3", 55 | "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", 56 | "gravatar_id": "", 57 | "url": "https://api.github.com/users/Codertocat", 58 | "html_url": "https://github.com/Codertocat", 59 | "followers_url": "https://api.github.com/users/Codertocat/followers", 60 | "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", 61 | "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", 62 | "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", 63 | "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", 64 | "organizations_url": "https://api.github.com/users/Codertocat/orgs", 65 | "repos_url": "https://api.github.com/users/Codertocat/repos", 66 | "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", 67 | "received_events_url": "https://api.github.com/users/Codertocat/received_events", 68 | "type": "User", 69 | "site_admin": false 70 | }, 71 | "private": false, 72 | "html_url": "https://github.com/Codertocat/Hello-World", 73 | "description": null, 74 | "fork": false, 75 | "url": "https://api.github.com/repos/Codertocat/Hello-World", 76 | "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks", 77 | "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}", 78 | "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}", 79 | "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams", 80 | "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks", 81 | "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}", 82 | "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events", 83 | "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}", 84 | "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}", 85 | "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags", 86 | "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}", 87 | "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}", 88 | "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}", 89 | "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}", 90 | "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}", 91 | "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages", 92 | "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers", 93 | "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors", 94 | "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers", 95 | "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription", 96 | "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}", 97 | "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}", 98 | "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}", 99 | "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}", 100 | "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}", 101 | "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}", 102 | "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges", 103 | "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}", 104 | "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads", 105 | "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}", 106 | "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}", 107 | "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}", 108 | "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}", 109 | "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}", 110 | "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}", 111 | "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments", 112 | "created_at": "2018-05-30T20:18:04Z", 113 | "updated_at": "2018-05-30T20:18:10Z", 114 | "pushed_at": "2018-05-30T20:18:30Z", 115 | "git_url": "git://github.com/Codertocat/Hello-World.git", 116 | "ssh_url": "git@github.com:Codertocat/Hello-World.git", 117 | "clone_url": "https://github.com/Codertocat/Hello-World.git", 118 | "svn_url": "https://github.com/Codertocat/Hello-World", 119 | "homepage": null, 120 | "size": 0, 121 | "stargazers_count": 0, 122 | "watchers_count": 0, 123 | "language": null, 124 | "has_issues": true, 125 | "has_projects": true, 126 | "has_downloads": true, 127 | "has_wiki": true, 128 | "has_pages": true, 129 | "forks_count": 0, 130 | "mirror_url": null, 131 | "archived": false, 132 | "open_issues_count": 2, 133 | "license": null, 134 | "forks": 0, 135 | "open_issues": 2, 136 | "watchers": 0, 137 | "default_branch": "master" 138 | }, 139 | "sender": { 140 | "login": "Codertocat", 141 | "id": 21031067, 142 | "node_id": "MDQ6VXNlcjIxMDMxMDY3", 143 | "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", 144 | "gravatar_id": "", 145 | "url": "https://api.github.com/users/Codertocat", 146 | "html_url": "https://github.com/Codertocat", 147 | "followers_url": "https://api.github.com/users/Codertocat/followers", 148 | "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", 149 | "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", 150 | "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", 151 | "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", 152 | "organizations_url": "https://api.github.com/users/Codertocat/orgs", 153 | "repos_url": "https://api.github.com/users/Codertocat/repos", 154 | "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", 155 | "received_events_url": "https://api.github.com/users/Codertocat/received_events", 156 | "type": "User", 157 | "site_admin": false 158 | } 159 | } -------------------------------------------------------------------------------- /test/payload/issues.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // empty issue payload 3 | nullIssue: { 4 | data: null, 5 | }, 6 | emptyIssue: { 7 | data: [], 8 | }, 9 | // Useless issue 10 | uselessIssue: { 11 | data: [ 12 | { 13 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 14 | number: 6, 15 | title: 'Weekly Digest test6', 16 | user: { 17 | type: 'USER', 18 | login: 'abhijeetps', 19 | html_url: 'https://github.com/abhijeetps', 20 | }, 21 | created_at: '2018-04-24T00:00:00Z', 22 | state: 'open', 23 | comments: 0, 24 | reactions: { 25 | '+1': 0, 26 | laugh: 0, 27 | hooray: 0, 28 | heart: 0, 29 | total_count: 0, 30 | }, 31 | }, 32 | { 33 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 34 | number: 5, 35 | title: 'Weekly Digest test5', 36 | user: { 37 | type: 'BOT', 38 | login: 'weekly-digest[bot]', 39 | html_url: 'https://github.com/abhijeetps', 40 | }, 41 | created_at: '2018-04-24T00:00:00Z', 42 | state: 'open', 43 | comments: 0, 44 | reactions: { 45 | '+1': 0, 46 | laugh: 0, 47 | hooray: 0, 48 | heart: 0, 49 | total_count: 0, 50 | }, 51 | }, 52 | { 53 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 54 | number: 3, 55 | title: 'Weekly Digest test3', 56 | user: { 57 | type: 'BOT', 58 | login: 'weekly-digest[bot]', 59 | html_url: 'https://github.com/abhijeetps', 60 | }, 61 | created_at: '2018-04-21T00:00:00Z', 62 | state: 'open', 63 | comments: 0, 64 | reactions: { 65 | '+1': 0, 66 | laugh: 0, 67 | hooray: 0, 68 | heart: 0, 69 | total_count: 0, 70 | }, 71 | }, 72 | { 73 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 74 | number: 2, 75 | title: 'Weekly Digest test2', 76 | user: { 77 | type: 'USER', 78 | login: 'abhijeetps', 79 | html_url: 'https://github.com/abhijeetps', 80 | }, 81 | created_at: '2018-04-16T00:00:00Z', 82 | state: 'open', 83 | comments: 0, 84 | reactions: { 85 | '+1': 0, 86 | laugh: 0, 87 | hooray: 0, 88 | heart: 0, 89 | total_count: 0, 90 | }, 91 | }, 92 | { 93 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 94 | number: 1, 95 | title: 'Weekly Digest test1', 96 | user: { 97 | type: 'BOT', 98 | login: 'weekly-digest[bot]', 99 | html_url: 'https://github.com/abhijeetps', 100 | }, 101 | created_at: '2018-04-16T00:00:00Z', 102 | state: 'open', 103 | comments: 0, 104 | reactions: { 105 | '+1': 0, 106 | laugh: 0, 107 | hooray: 0, 108 | heart: 0, 109 | total_count: 0, 110 | }, 111 | }, 112 | ], 113 | }, 114 | // Open issue payload 115 | openIssue: { 116 | data: [ 117 | { 118 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 119 | number: 6, 120 | title: 'Weekly Digest test6', 121 | user: { 122 | type: 'USER', 123 | login: 'abhijeetps', 124 | html_url: 'https://github.com/abhijeetps', 125 | }, 126 | created_at: '2018-04-24T00:00:00Z', 127 | state: 'open', 128 | comments: 0, 129 | reactions: { 130 | '+1': 0, 131 | laugh: 0, 132 | hooray: 0, 133 | heart: 0, 134 | total_count: 0, 135 | }, 136 | }, 137 | { 138 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 139 | number: 5, 140 | title: 'Weekly Digest test5', 141 | user: { 142 | type: 'BOT', 143 | login: 'weekly-digest[bot]', 144 | html_url: 'https://github.com/abhijeetps', 145 | }, 146 | created_at: '2018-04-24T00:00:00Z', 147 | state: 'open', 148 | comments: 0, 149 | reactions: { 150 | '+1': 0, 151 | laugh: 0, 152 | hooray: 0, 153 | heart: 0, 154 | total_count: 0, 155 | }, 156 | }, 157 | { 158 | html_url: 'https://github.com/abhijeetps/playground/issues/4', 159 | number: 4, 160 | title: 'Weekly Digest test4', 161 | user: { 162 | type: 'USER', 163 | login: 'abhijeetps', 164 | html_url: 'https://github.com/abhijeetps', 165 | }, 166 | created_at: '2018-04-21T00:00:00Z', 167 | state: 'open', 168 | comments: 0, 169 | reactions: { 170 | '+1': 0, 171 | laugh: 0, 172 | hooray: 0, 173 | heart: 0, 174 | total_count: 0, 175 | }, 176 | }, 177 | { 178 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 179 | number: 3, 180 | title: 'Weekly Digest test3', 181 | user: { 182 | type: 'BOT', 183 | login: 'weekly-digest[bot]', 184 | html_url: 'https://github.com/abhijeetps', 185 | }, 186 | created_at: '2018-04-21T00:00:00Z', 187 | state: 'open', 188 | comments: 0, 189 | reactions: { 190 | '+1': 0, 191 | laugh: 0, 192 | hooray: 0, 193 | heart: 0, 194 | total_count: 0, 195 | }, 196 | }, 197 | { 198 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 199 | number: 2, 200 | title: 'Weekly Digest test2', 201 | user: { 202 | type: 'USER', 203 | login: 'abhijeetps', 204 | html_url: 'https://github.com/abhijeetps', 205 | }, 206 | created_at: '2018-04-16T00:00:00Z', 207 | state: 'open', 208 | comments: 0, 209 | reactions: { 210 | '+1': 0, 211 | laugh: 0, 212 | hooray: 0, 213 | heart: 0, 214 | total_count: 0, 215 | }, 216 | }, 217 | { 218 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 219 | number: 1, 220 | title: 'Weekly Digest test1', 221 | user: { 222 | type: 'BOT', 223 | login: 'weekly-digest[bot]', 224 | html_url: 'https://github.com/abhijeetps', 225 | }, 226 | created_at: '2018-04-16T00:00:00Z', 227 | state: 'open', 228 | comments: 0, 229 | reactions: { 230 | '+1': 0, 231 | laugh: 0, 232 | hooray: 0, 233 | heart: 0, 234 | total_count: 0, 235 | }, 236 | }, 237 | ], 238 | }, 239 | // Closed issue payload 240 | closedIssue: { 241 | data: [ 242 | { 243 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 244 | number: 6, 245 | title: 'Weekly Digest test6', 246 | user: { 247 | type: 'USER', 248 | login: 'abhijeetps', 249 | html_url: 'https://github.com/abhijeetps', 250 | }, 251 | created_at: '2018-04-24T00:00:00Z', 252 | state: 'closed', 253 | comments: 0, 254 | reactions: { 255 | '+1': 0, 256 | laugh: 0, 257 | hooray: 0, 258 | heart: 0, 259 | total_count: 0, 260 | }, 261 | }, 262 | { 263 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 264 | number: 5, 265 | title: 'Weekly Digest test5', 266 | user: { 267 | type: 'BOT', 268 | login: 'weekly-digest[bot]', 269 | html_url: 'https://github.com/abhijeetps', 270 | }, 271 | created_at: '2018-04-24T00:00:00Z', 272 | state: 'closed', 273 | comments: 0, 274 | reactions: { 275 | '+1': 0, 276 | laugh: 0, 277 | hooray: 0, 278 | heart: 0, 279 | total_count: 0, 280 | }, 281 | }, 282 | { 283 | html_url: 'https://github.com/abhijeetps/playground/issues/4', 284 | number: 4, 285 | title: 'Weekly Digest test4', 286 | user: { 287 | type: 'USER', 288 | login: 'abhijeetps', 289 | html_url: 'https://github.com/abhijeetps', 290 | }, 291 | created_at: '2018-04-21T00:00:00Z', 292 | state: 'closed', 293 | comments: 0, 294 | reactions: { 295 | '+1': 0, 296 | laugh: 0, 297 | hooray: 0, 298 | heart: 0, 299 | total_count: 0, 300 | }, 301 | }, 302 | { 303 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 304 | number: 3, 305 | title: 'Weekly Digest test3', 306 | user: { 307 | type: 'BOT', 308 | login: 'weekly-digest[bot]', 309 | html_url: 'https://github.com/abhijeetps', 310 | }, 311 | created_at: '2018-04-21T00:00:00Z', 312 | state: 'closed', 313 | comments: 0, 314 | reactions: { 315 | '+1': 0, 316 | laugh: 0, 317 | hooray: 0, 318 | heart: 0, 319 | total_count: 0, 320 | }, 321 | }, 322 | { 323 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 324 | number: 2, 325 | title: 'Weekly Digest test2', 326 | user: { 327 | type: 'USER', 328 | login: 'abhijeetps', 329 | html_url: 'https://github.com/abhijeetps', 330 | }, 331 | created_at: '2018-04-16T00:00:00Z', 332 | state: 'closed', 333 | comments: 0, 334 | reactions: { 335 | '+1': 0, 336 | laugh: 0, 337 | hooray: 0, 338 | heart: 0, 339 | total_count: 0, 340 | }, 341 | }, 342 | { 343 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 344 | number: 1, 345 | title: 'Weekly Digest test1', 346 | user: { 347 | type: 'BOT', 348 | login: 'weekly-digest[bot]', 349 | html_url: 'https://github.com/abhijeetps', 350 | }, 351 | created_at: '2018-04-16T00:00:00Z', 352 | state: 'closed', 353 | comments: 0, 354 | reactions: { 355 | '+1': 0, 356 | laugh: 0, 357 | hooray: 0, 358 | heart: 0, 359 | total_count: 0, 360 | }, 361 | }, 362 | ], 363 | }, 364 | noisyIssue: { 365 | data: [ 366 | { 367 | html_url: 'https://github.com/abhijeetps/playground/issues/9', 368 | number: 9, 369 | title: 'Weekly Digest test9', 370 | user: { 371 | type: 'BOT', 372 | login: 'weekly-digest[bot]', 373 | html_url: 'https://github.com/abhijeetps', 374 | }, 375 | created_at: '2018-04-24T00:00:00Z', 376 | state: 'open', 377 | comments: 6, 378 | reactions: { 379 | '+1': 0, 380 | laugh: 0, 381 | hooray: 0, 382 | heart: 0, 383 | total_count: 0, 384 | }, 385 | }, 386 | { 387 | html_url: 'https://github.com/abhijeetps/playground/issues/8', 388 | number: 8, 389 | title: 'Weekly Digest test8', 390 | user: { 391 | type: 'USER', 392 | login: 'abhijeetps', 393 | html_url: 'https://github.com/abhijeetps', 394 | }, 395 | created_at: '2018-04-24T00:00:00Z', 396 | state: 'open', 397 | comments: 3, 398 | reactions: { 399 | '+1': 0, 400 | laugh: 0, 401 | hooray: 0, 402 | heart: 0, 403 | total_count: 0, 404 | }, 405 | }, 406 | { 407 | html_url: 'https://github.com/abhijeetps/playground/issues/7', 408 | number: 7, 409 | title: 'Weekly Digest test7', 410 | user: { 411 | type: 'USER', 412 | login: 'abhijeetps', 413 | html_url: 'https://github.com/abhijeetps', 414 | }, 415 | created_at: '2018-04-24T00:00:00Z', 416 | state: 'closed', 417 | comments: 0, 418 | reactions: { 419 | '+1': 0, 420 | laugh: 0, 421 | hooray: 0, 422 | heart: 0, 423 | total_count: 0, 424 | }, 425 | }, 426 | { 427 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 428 | number: 6, 429 | title: 'Weekly Digest test6', 430 | user: { 431 | type: 'BOT', 432 | login: 'weekly-digest[bot]', 433 | html_url: 'https://github.com/abhijeetps', 434 | }, 435 | created_at: '2018-04-21T00:00:00Z', 436 | state: 'open', 437 | comments: 10, 438 | reactions: { 439 | '+1': 0, 440 | laugh: 0, 441 | hooray: 0, 442 | heart: 0, 443 | total_count: 0, 444 | }, 445 | }, 446 | { 447 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 448 | number: 5, 449 | title: 'Weekly Digest test5', 450 | user: { 451 | type: 'USER', 452 | login: 'abhijeetps', 453 | html_url: 'https://github.com/abhijeetps', 454 | }, 455 | created_at: '2018-04-20T00:00:00Z', 456 | state: 'open', 457 | comments: 3, 458 | reactions: { 459 | '+1': 0, 460 | laugh: 0, 461 | hooray: 0, 462 | heart: 0, 463 | total_count: 0, 464 | }, 465 | }, 466 | { 467 | html_url: 'https://github.com/abhijeetps/playground/issues/4', 468 | number: 4, 469 | title: 'Weekly Digest test4', 470 | user: { 471 | type: 'USER', 472 | login: 'abhijeetps', 473 | html_url: 'https://github.com/abhijeetps', 474 | }, 475 | created_at: '2018-04-19T00:00:00Z', 476 | state: 'closed', 477 | comments: 7, 478 | reactions: { 479 | '+1': 0, 480 | laugh: 0, 481 | hooray: 0, 482 | heart: 0, 483 | total_count: 0, 484 | }, 485 | }, 486 | { 487 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 488 | number: 3, 489 | title: 'Weekly Digest test3', 490 | user: { 491 | type: 'BOT', 492 | login: 'weekly-digest[bot]', 493 | html_url: 'https://github.com/abhijeetps', 494 | }, 495 | created_at: '2018-04-16T00:00:00Z', 496 | state: 'open', 497 | comments: 1, 498 | reactions: { 499 | '+1': 0, 500 | laugh: 0, 501 | hooray: 0, 502 | heart: 0, 503 | total_count: 0, 504 | }, 505 | }, 506 | { 507 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 508 | number: 2, 509 | title: 'Weekly Digest test2', 510 | user: { 511 | type: 'USER', 512 | login: 'abhijeetps', 513 | html_url: 'https://github.com/abhijeetps', 514 | }, 515 | created_at: '2018-04-16T00:00:00Z', 516 | state: 'open', 517 | comments: 2, 518 | reactions: { 519 | '+1': 0, 520 | laugh: 0, 521 | hooray: 0, 522 | heart: 0, 523 | total_count: 0, 524 | }, 525 | }, 526 | { 527 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 528 | number: 1, 529 | title: 'Weekly Digest test1', 530 | user: { 531 | type: 'USER', 532 | login: 'abhijeetps', 533 | html_url: 'https://github.com/abhijeetps', 534 | }, 535 | created_at: '2018-04-16T00:00:00Z', 536 | state: 'closed', 537 | comments: 3, 538 | reactions: { 539 | '+1': 0, 540 | laugh: 0, 541 | hooray: 0, 542 | heart: 0, 543 | total_count: 0, 544 | }, 545 | }, 546 | ], 547 | }, 548 | likedIssue: { 549 | data: [ 550 | { 551 | html_url: 'https://github.com/abhijeetps/playground/issues/9', 552 | number: 9, 553 | title: 'Weekly Digest test9', 554 | user: { 555 | type: 'BOT', 556 | login: 'weekly-digest[bot]', 557 | html_url: 'https://github.com/abhijeetps', 558 | }, 559 | created_at: '2018-04-24T00:00:00Z', 560 | state: 'open', 561 | comments: 0, 562 | reactions: { 563 | '+1': 1, 564 | laugh: 1, 565 | hooray: 1, 566 | heart: 1, 567 | total_count: 5, 568 | }, 569 | }, 570 | { 571 | html_url: 'https://github.com/abhijeetps/playground/issues/8', 572 | number: 8, 573 | title: 'Weekly Digest test8', 574 | user: { 575 | type: 'USER', 576 | login: 'abhijeetps', 577 | html_url: 'https://github.com/abhijeetps', 578 | }, 579 | created_at: '2018-04-24T00:00:00Z', 580 | state: 'open', 581 | comments: 0, 582 | reactions: { 583 | '+1': 1, 584 | laugh: 1, 585 | hooray: 1, 586 | heart: 1, 587 | total_count: 5, 588 | }, 589 | }, 590 | { 591 | html_url: 'https://github.com/abhijeetps/playground/issues/7', 592 | number: 7, 593 | title: 'Weekly Digest test7', 594 | user: { 595 | type: 'USER', 596 | login: 'abhijeetps', 597 | html_url: 'https://github.com/abhijeetps', 598 | }, 599 | created_at: '2018-04-24T00:00:00Z', 600 | state: 'closed', 601 | comments: 0, 602 | reactions: { 603 | '+1': 1, 604 | laugh: 1, 605 | hooray: 1, 606 | heart: 1, 607 | total_count: 5, 608 | }, 609 | }, 610 | { 611 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 612 | number: 6, 613 | title: 'Weekly Digest test6', 614 | user: { 615 | type: 'BOT', 616 | login: 'weekly-digest[bot]', 617 | html_url: 'https://github.com/abhijeetps', 618 | }, 619 | created_at: '2018-04-21T00:00:00Z', 620 | state: 'open', 621 | comments: 0, 622 | reactions: { 623 | '+1': 4, 624 | laugh: 4, 625 | hooray: 4, 626 | heart: 4, 627 | total_count: 20, 628 | }, 629 | }, 630 | { 631 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 632 | number: 5, 633 | title: 'Weekly Digest test5', 634 | user: { 635 | type: 'USER', 636 | login: 'abhijeetps', 637 | html_url: 'https://github.com/abhijeetps', 638 | }, 639 | created_at: '2018-04-20T00:00:00Z', 640 | state: 'open', 641 | comments: 0, 642 | reactions: { 643 | '+1': 2, 644 | laugh: 2, 645 | hooray: 1, 646 | heart: 3, 647 | total_count: 10, 648 | }, 649 | }, 650 | { 651 | html_url: 'https://github.com/abhijeetps/playground/issues/4', 652 | number: 4, 653 | title: 'Weekly Digest test4', 654 | user: { 655 | type: 'USER', 656 | login: 'abhijeetps', 657 | html_url: 'https://github.com/abhijeetps', 658 | }, 659 | created_at: '2018-04-19T00:00:00Z', 660 | state: 'closed', 661 | comments: 0, 662 | reactions: { 663 | '+1': 3, 664 | laugh: 2, 665 | hooray: 5, 666 | heart: 2, 667 | total_count: 15, 668 | }, 669 | }, 670 | { 671 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 672 | number: 3, 673 | title: 'Weekly Digest test3', 674 | user: { 675 | type: 'BOT', 676 | login: 'weekly-digest[bot]', 677 | html_url: 'https://github.com/abhijeetps', 678 | }, 679 | created_at: '2018-04-16T00:00:00Z', 680 | state: 'open', 681 | comments: 0, 682 | reactions: { 683 | '+1': 2, 684 | laugh: 2, 685 | hooray: 2, 686 | heart: 2, 687 | total_count: 10, 688 | }, 689 | }, 690 | { 691 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 692 | number: 2, 693 | title: 'Weekly Digest test2', 694 | user: { 695 | type: 'USER', 696 | login: 'abhijeetps', 697 | html_url: 'https://github.com/abhijeetps', 698 | }, 699 | created_at: '2018-04-16T00:00:00Z', 700 | state: 'open', 701 | comments: 0, 702 | reactions: { 703 | '+1': 2, 704 | laugh: 2, 705 | hooray: 2, 706 | heart: 2, 707 | total_count: 10, 708 | }, 709 | }, 710 | { 711 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 712 | number: 1, 713 | title: 'Weekly Digest test1', 714 | user: { 715 | type: 'USER', 716 | login: 'abhijeetps', 717 | html_url: 'https://github.com/abhijeetps', 718 | }, 719 | created_at: '2018-04-16T00:00:00Z', 720 | state: 'closed', 721 | comments: 0, 722 | reactions: { 723 | '+1': 2, 724 | laugh: 2, 725 | hooray: 2, 726 | heart: 2, 727 | total_count: 10, 728 | }, 729 | }, 730 | ], 731 | }, 732 | // All issues payload 733 | allIssueA: { 734 | data: [ 735 | { 736 | html_url: 'https://github.com/abhijeetps/playground/issues/12', 737 | number: 12, 738 | title: 'Weekly Digest test12', 739 | user: { 740 | type: 'BOT', 741 | login: 'weekly-digest[bot]', 742 | html_url: 'https://github.com/abhijeetps', 743 | }, 744 | created_at: '2018-04-24T00:00:00Z', 745 | state: 'open', 746 | comments: 2, 747 | reactions: { 748 | '+1': 1, 749 | laugh: 1, 750 | hooray: 1, 751 | heart: 1, 752 | total_count: 5, 753 | }, 754 | }, 755 | { 756 | html_url: 'https://github.com/abhijeetps/playground/issues/11', 757 | number: 11, 758 | title: 'Weekly Digest test11', 759 | created_at: '2018-04-24T00:00:00Z', 760 | user: { 761 | type: 'BOT', 762 | login: 'weekly-digest[bot]', 763 | html_url: 'https://github.com/abhijeetps', 764 | }, 765 | state: 'closed', 766 | comments: 3, 767 | reactions: { 768 | '+1': 1, 769 | laugh: 1, 770 | hooray: 1, 771 | heart: 1, 772 | total_count: 5, 773 | }, 774 | }, 775 | { 776 | html_url: 'https://github.com/abhijeetps/playground/issues/10', 777 | number: 10, 778 | title: 'Weekly Digest test10', 779 | created_at: '2018-04-24T00:00:00Z', 780 | user: { 781 | type: 'USER', 782 | login: 'abhijeetps', 783 | html_url: 'https://github.com/abhijeetps', 784 | }, 785 | state: 'open', 786 | comments: 4, 787 | reactions: { 788 | '+1': 1, 789 | laugh: 1, 790 | hooray: 1, 791 | heart: 1, 792 | total_count: 5, 793 | }, 794 | }, 795 | { 796 | html_url: 'https://github.com/abhijeetps/playground/issues/9', 797 | number: 9, 798 | title: 'Weekly Digest test9', 799 | created_at: '2018-04-24T00:00:00Z', 800 | user: { 801 | type: 'USER', 802 | login: 'abhijeetps', 803 | html_url: 'https://github.com/abhijeetps', 804 | }, 805 | state: 'closed', 806 | comments: 10, 807 | reactions: { 808 | '+1': 2, 809 | laugh: 2, 810 | hooray: 2, 811 | heart: 2, 812 | total_count: 8, 813 | }, 814 | }, 815 | { 816 | html_url: 'https://github.com/abhijeetps/playground/issues/8', 817 | number: 8, 818 | title: 'Weekly Digest test8', 819 | user: { 820 | type: 'BOT', 821 | login: 'weekly-digest[bot]', 822 | html_url: 'https://github.com/abhijeetps', 823 | }, 824 | created_at: '2018-04-22T00:00:00Z', 825 | state: 'open', 826 | comments: 20, 827 | reactions: { 828 | '+1': 4, 829 | laugh: 4, 830 | hooray: 4, 831 | heart: 4, 832 | total_count: 20, 833 | }, 834 | }, 835 | { 836 | html_url: 'https://github.com/abhijeetps/playground/issues/7', 837 | number: 7, 838 | title: 'Weekly Digest test7', 839 | created_at: '2018-04-21T00:00:00Z', 840 | user: { 841 | type: 'BOT', 842 | login: 'weekly-digest[bot]', 843 | html_url: 'https://github.com/abhijeetps', 844 | }, 845 | state: 'closed', 846 | comments: 15, 847 | reactions: { 848 | '+1': 3, 849 | laugh: 3, 850 | hooray: 3, 851 | heart: 3, 852 | total_count: 15, 853 | }, 854 | }, 855 | { 856 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 857 | number: 6, 858 | title: 'Weekly Digest test6', 859 | created_at: '2018-04-20T00:00:00Z', 860 | user: { 861 | type: 'USER', 862 | login: 'abhijeetps', 863 | html_url: 'https://github.com/abhijeetps', 864 | }, 865 | state: 'open', 866 | comments: 6, 867 | reactions: { 868 | '+1': 1, 869 | laugh: 0, 870 | hooray: 0, 871 | heart: 1, 872 | total_count: 4, 873 | }, 874 | }, 875 | { 876 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 877 | number: 5, 878 | title: 'Weekly Digest test5', 879 | created_at: '2018-04-19T00:00:00Z', 880 | user: { 881 | type: 'USER', 882 | login: 'abhijeetps', 883 | html_url: 'https://github.com/abhijeetps', 884 | }, 885 | state: 'closed', 886 | comments: 4, 887 | reactions: { 888 | '+1': 2, 889 | laugh: 3, 890 | hooray: 1, 891 | heart: 2, 892 | total_count: 10, 893 | }, 894 | }, 895 | { 896 | html_url: 'https://github.com/abhijeetps/playground/issues/4', 897 | number: 4, 898 | title: 'Weekly Digest test4', 899 | user: { 900 | type: 'BOT', 901 | login: 'weekly-digest[bot]', 902 | html_url: 'https://github.com/abhijeetps', 903 | }, 904 | created_at: '2018-04-16T00:00:00Z', 905 | state: 'open', 906 | comments: 2, 907 | reactions: { 908 | '+1': 4, 909 | laugh: 4, 910 | hooray: 4, 911 | heart: 4, 912 | total_count: 20, 913 | }, 914 | }, 915 | { 916 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 917 | number: 3, 918 | title: 'Weekly Digest test3', 919 | created_at: '2018-04-16T00:00:00Z', 920 | user: { 921 | type: 'BOT', 922 | login: 'weekly-digest[bot]', 923 | html_url: 'https://github.com/abhijeetps', 924 | }, 925 | state: 'closed', 926 | comments: 3, 927 | reactions: { 928 | '+1': 3, 929 | laugh: 3, 930 | hooray: 3, 931 | heart: 3, 932 | total_count: 15, 933 | }, 934 | }, 935 | { 936 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 937 | number: 2, 938 | title: 'Weekly Digest test2', 939 | created_at: '2018-04-16T00:00:00Z', 940 | user: { 941 | type: 'USER', 942 | login: 'abhijeetps', 943 | html_url: 'https://github.com/abhijeetps', 944 | }, 945 | state: 'open', 946 | comments: 4, 947 | reactions: { 948 | '+1': 2, 949 | laugh: 2, 950 | hooray: 2, 951 | heart: 2, 952 | total_count: 8, 953 | }, 954 | }, 955 | { 956 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 957 | number: 1, 958 | title: 'Weekly Digest test1', 959 | created_at: '2018-04-16T00:00:00Z', 960 | user: { 961 | type: 'USER', 962 | login: 'abhijeetps', 963 | html_url: 'https://github.com/abhijeetps', 964 | }, 965 | state: 'closed', 966 | comments: 10, 967 | reactions: { 968 | '+1': 1, 969 | laugh: 1, 970 | hooray: 1, 971 | heart: 1, 972 | total_count: 4, 973 | }, 974 | }, 975 | ], 976 | }, 977 | allIssueB: { 978 | data: [ 979 | { 980 | html_url: 'https://github.com/abhijeetps/playground/issues/12', 981 | number: 12, 982 | title: 'Weekly Digest test12', 983 | user: { 984 | type: 'BOT', 985 | login: 'weekly-digest[bot]', 986 | html_url: 'https://github.com/abhijeetps', 987 | }, 988 | created_at: '2018-04-24T00:00:00Z', 989 | state: 'open', 990 | comments: 2, 991 | reactions: { 992 | '+1': 1, 993 | laugh: 1, 994 | hooray: 1, 995 | heart: 1, 996 | total_count: 5, 997 | }, 998 | }, 999 | { 1000 | html_url: 'https://github.com/abhijeetps/playground/issues/11', 1001 | number: 11, 1002 | title: 'Weekly Digest test11', 1003 | created_at: '2018-04-24T00:00:00Z', 1004 | user: { 1005 | type: 'BOT', 1006 | login: 'weekly-digest[bot]', 1007 | html_url: 'https://github.com/abhijeetps', 1008 | }, 1009 | state: 'closed', 1010 | comments: 3, 1011 | reactions: { 1012 | '+1': 1, 1013 | laugh: 1, 1014 | hooray: 1, 1015 | heart: 1, 1016 | total_count: 5, 1017 | }, 1018 | }, 1019 | { 1020 | html_url: 'https://github.com/abhijeetps/playground/issues/10', 1021 | number: 10, 1022 | title: 'Weekly Digest test10', 1023 | created_at: '2018-04-24T00:00:00Z', 1024 | user: { 1025 | type: 'USER', 1026 | login: 'abhijeetps', 1027 | html_url: 'https://github.com/abhijeetps', 1028 | }, 1029 | state: 'open', 1030 | comments: 4, 1031 | reactions: { 1032 | '+1': 1, 1033 | laugh: 1, 1034 | hooray: 1, 1035 | heart: 1, 1036 | total_count: 5, 1037 | }, 1038 | }, 1039 | { 1040 | html_url: 'https://github.com/abhijeetps/playground/issues/9', 1041 | number: 9, 1042 | title: 'Weekly Digest test9', 1043 | created_at: '2018-04-24T00:00:00Z', 1044 | user: { 1045 | type: 'USER', 1046 | login: 'abhijeetps', 1047 | html_url: 'https://github.com/abhijeetps', 1048 | }, 1049 | state: 'closed', 1050 | comments: 10, 1051 | reactions: { 1052 | '+1': 2, 1053 | laugh: 2, 1054 | hooray: 2, 1055 | heart: 2, 1056 | total_count: 8, 1057 | }, 1058 | }, 1059 | { 1060 | html_url: 'https://github.com/abhijeetps/playground/issues/8', 1061 | number: 8, 1062 | title: 'Weekly Digest test8', 1063 | user: { 1064 | type: 'BOT', 1065 | login: 'weekly-digest[bot]', 1066 | html_url: 'https://github.com/abhijeetps', 1067 | }, 1068 | created_at: '2018-04-22T00:00:00Z', 1069 | state: 'open', 1070 | comments: 20, 1071 | reactions: { 1072 | '+1': 4, 1073 | laugh: 4, 1074 | hooray: 4, 1075 | heart: 4, 1076 | total_count: 20, 1077 | }, 1078 | }, 1079 | { 1080 | html_url: 'https://github.com/abhijeetps/playground/issues/7', 1081 | number: 7, 1082 | title: 'Weekly Digest test7', 1083 | created_at: '2018-04-21T00:00:00Z', 1084 | user: { 1085 | type: 'BOT', 1086 | login: 'weekly-digest[bot]', 1087 | html_url: 'https://github.com/abhijeetps', 1088 | }, 1089 | state: 'closed', 1090 | comments: 15, 1091 | reactions: { 1092 | '+1': 3, 1093 | laugh: 3, 1094 | hooray: 3, 1095 | heart: 3, 1096 | total_count: 15, 1097 | }, 1098 | }, 1099 | { 1100 | html_url: 'https://github.com/abhijeetps/playground/issues/6', 1101 | number: 6, 1102 | title: 'Weekly Digest test6', 1103 | created_at: '2018-04-20T00:00:00Z', 1104 | user: { 1105 | type: 'USER', 1106 | login: 'abhijeetps', 1107 | html_url: 'https://github.com/abhijeetps', 1108 | }, 1109 | state: 'open', 1110 | comments: 4, 1111 | reactions: { 1112 | '+1': 2, 1113 | laugh: 3, 1114 | hooray: 1, 1115 | heart: 2, 1116 | total_count: 10, 1117 | }, 1118 | }, 1119 | { 1120 | html_url: 'https://github.com/abhijeetps/playground/issues/5', 1121 | number: 5, 1122 | title: 'Weekly Digest test5', 1123 | created_at: '2018-04-19T00:00:00Z', 1124 | user: { 1125 | type: 'USER', 1126 | login: 'abhijeetps', 1127 | html_url: 'https://github.com/abhijeetps', 1128 | }, 1129 | state: 'closed', 1130 | comments: 6, 1131 | reactions: { 1132 | '+1': 1, 1133 | laugh: 0, 1134 | hooray: 0, 1135 | heart: 1, 1136 | total_count: 4, 1137 | }, 1138 | }, 1139 | { 1140 | html_url: 'https://github.com/abhijeetps/playground/issues/4', 1141 | number: 4, 1142 | title: 'Weekly Digest test4', 1143 | user: { 1144 | type: 'BOT', 1145 | login: 'weekly-digest[bot]', 1146 | html_url: 'https://github.com/abhijeetps', 1147 | }, 1148 | created_at: '2018-04-16T00:00:00Z', 1149 | state: 'open', 1150 | comments: 2, 1151 | reactions: { 1152 | '+1': 4, 1153 | laugh: 4, 1154 | hooray: 4, 1155 | heart: 4, 1156 | total_count: 20, 1157 | }, 1158 | }, 1159 | { 1160 | html_url: 'https://github.com/abhijeetps/playground/issues/3', 1161 | number: 3, 1162 | title: 'Weekly Digest test3', 1163 | created_at: '2018-04-16T00:00:00Z', 1164 | user: { 1165 | type: 'BOT', 1166 | login: 'weekly-digest[bot]', 1167 | html_url: 'https://github.com/abhijeetps', 1168 | }, 1169 | state: 'closed', 1170 | comments: 3, 1171 | reactions: { 1172 | '+1': 3, 1173 | laugh: 3, 1174 | hooray: 3, 1175 | heart: 3, 1176 | total_count: 15, 1177 | }, 1178 | }, 1179 | { 1180 | html_url: 'https://github.com/abhijeetps/playground/issues/2', 1181 | number: 2, 1182 | title: 'Weekly Digest test2', 1183 | created_at: '2018-04-16T00:00:00Z', 1184 | user: { 1185 | type: 'USER', 1186 | login: 'abhijeetps', 1187 | html_url: 'https://github.com/abhijeetps', 1188 | }, 1189 | state: 'open', 1190 | comments: 4, 1191 | reactions: { 1192 | '+1': 2, 1193 | laugh: 2, 1194 | hooray: 2, 1195 | heart: 2, 1196 | total_count: 8, 1197 | }, 1198 | }, 1199 | { 1200 | html_url: 'https://github.com/abhijeetps/playground/issues/1', 1201 | number: 1, 1202 | title: 'Weekly Digest test1', 1203 | created_at: '2018-04-16T00:00:00Z', 1204 | user: { 1205 | type: 'USER', 1206 | login: 'abhijeetps', 1207 | html_url: 'https://github.com/abhijeetps', 1208 | }, 1209 | state: 'closed', 1210 | comments: 10, 1211 | reactions: { 1212 | '+1': 1, 1213 | laugh: 1, 1214 | hooray: 1, 1215 | heart: 1, 1216 | total_count: 4, 1217 | }, 1218 | }, 1219 | ], 1220 | }, 1221 | }; 1222 | -------------------------------------------------------------------------------- /test/payload/pullRequests.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | nullPullRequest: { 3 | data: null, 4 | }, 5 | emptyPullRequest: { 6 | data: [], 7 | }, 8 | uselessPullRequest: { 9 | data: [ 10 | // newer 11 | { 12 | html_url: 'https://github.com/abhijeetps/playground/pull/36', 13 | number: 36, 14 | state: 'closed', 15 | title: 'Weekly Digest test36', 16 | user: { 17 | login: 'abhijeetps', 18 | html_url: 'https://github.com/abhijeetps', 19 | }, 20 | created_at: '2018-04-24T00:00:00Z', 21 | updated_at: '2018-04-25T00:00:00Z', 22 | merged_at: '2018-04-26T00:00:00Z', 23 | }, 24 | { 25 | html_url: 'https://github.com/abhijeetps/playground/pull/35', 26 | number: 35, 27 | state: 'closed', 28 | title: 'Weekly Digest test35', 29 | user: { 30 | login: 'weekly-digest[bot]', 31 | html_url: 'https://github.com/apps/weekly-digest', 32 | }, 33 | created_at: '2018-04-24T00:00:00Z', 34 | updated_at: '2018-04-25T00:00:00Z', 35 | merged_at: '2018-04-26T00:00:00Z', 36 | }, 37 | { 38 | html_url: 'https://github.com/abhijeetps/playground/pull/34', 39 | number: 34, 40 | state: 'closed', 41 | title: 'Weekly Digest test34', 42 | user: { 43 | login: 'abhijeetps', 44 | html_url: 'https://github.com/abhijeetps', 45 | }, 46 | created_at: '2018-04-24T00:00:00Z', 47 | updated_at: '2018-04-25T00:00:00Z', 48 | merged_at: null, 49 | }, 50 | { 51 | html_url: 'https://github.com/abhijeetps/playground/pull/33', 52 | number: 33, 53 | state: 'closed', 54 | title: 'Weekly Digest test33', 55 | user: { 56 | login: 'weekly-digest[bot]', 57 | html_url: 'https://github.com/apps/weekly-digest', 58 | }, 59 | created_at: '2018-04-24T00:00:00Z', 60 | updated_at: '2018-04-25T00:00:00Z', 61 | merged_at: null, 62 | }, 63 | { 64 | html_url: 'https://github.com/abhijeetps/playground/pull/32', 65 | number: 32, 66 | state: 'closed', 67 | title: 'Weekly Digest test32', 68 | user: { 69 | login: 'abhijeetps', 70 | html_url: 'https://github.com/abhijeetps', 71 | }, 72 | created_at: '2018-04-24T00:00:00Z', 73 | updated_at: '2018-04-24T00:00:00Z', 74 | merged_at: null, 75 | }, 76 | { 77 | html_url: 'https://github.com/abhijeetps/playground/pull/31', 78 | number: 31, 79 | state: 'closed', 80 | title: 'Weekly Digest test31', 81 | user: { 82 | login: 'weekly-digest[bot]', 83 | html_url: 'https://github.com/app/weekly-digest', 84 | }, 85 | created_at: '2018-04-24T00:00:00Z', 86 | updated_at: '2018-04-24T00:00:00Z', 87 | merged_at: null, 88 | }, 89 | { 90 | html_url: 'https://github.com/abhijeetps/playground/pull/30', 91 | number: 30, 92 | state: 'open', 93 | title: 'Weekly Digest test30', 94 | user: { 95 | login: 'abhijeetps', 96 | html_url: 'https://github.com/abhijeetps', 97 | }, 98 | created_at: '2018-04-24T00:00:00Z', 99 | updated_at: '2018-04-25T00:00:00Z', 100 | merged_at: '2018-04-26T00:00:00Z', 101 | }, 102 | { 103 | html_url: 'https://github.com/abhijeetps/playground/pull/29', 104 | number: 29, 105 | state: 'open', 106 | title: 'Weekly Digest test29', 107 | user: { 108 | login: 'weekly-digest[bot]', 109 | html_url: 'https://github.com/app/weekly-digest', 110 | }, 111 | created_at: '2018-04-24T00:00:00Z', 112 | updated_at: '2018-04-25T00:00:00Z', 113 | merged_at: '2018-04-26T00:00:00Z', 114 | }, 115 | { 116 | html_url: 'https://github.com/abhijeetps/playground/pull/28', 117 | number: 28, 118 | state: 'open', 119 | title: 'Weekly Digest test28', 120 | user: { 121 | login: 'abhijeetps', 122 | html_url: 'https://github.com/abhijeetps', 123 | }, 124 | created_at: '2018-04-24T00:00:00Z', 125 | updated_at: '2018-04-25T00:00:00Z', 126 | merged_at: null, 127 | }, 128 | { 129 | html_url: 'https://github.com/abhijeetps/playground/pull/27', 130 | number: 27, 131 | state: 'open', 132 | title: 'Weekly Digest test27', 133 | user: { 134 | login: 'weekly-digest[bot]', 135 | html_url: 'https://github.com/app/weekly-digest', 136 | }, 137 | created_at: '2018-04-24T00:00:00Z', 138 | updated_at: '2018-04-25T00:00:00Z', 139 | merged_at: null, 140 | }, 141 | { 142 | html_url: 'https://github.com/abhijeetps/playground/pull/26', 143 | number: 26, 144 | state: 'open', 145 | title: 'Weekly Digest test26', 146 | user: { 147 | login: 'abhijeetps', 148 | html_url: 'https://github.com/abhijeetps', 149 | }, 150 | created_at: '2018-04-24T00:00:00Z', 151 | updated_at: '2018-04-24T00:00:00Z', 152 | merged_at: null, 153 | }, 154 | { 155 | html_url: 'https://github.com/abhijeetps/playground/pull/25', 156 | number: 25, 157 | state: 'open', 158 | title: 'Weekly Digest test25', 159 | user: { 160 | login: 'weekly-digest[bot]', 161 | html_url: 'https://github.com/app/weekly-digest', 162 | }, 163 | created_at: '2018-04-24T00:00:00Z', 164 | updated_at: '2018-04-24T00:00:00Z', 165 | merged_at: null, 166 | }, 167 | // current 168 | { 169 | html_url: 'https://github.com/abhijeetps/playground/pull/23', 170 | number: 23, 171 | state: 'closed', 172 | title: 'Weekly Digest test23', 173 | user: { 174 | login: 'weekly-digest[bot]', 175 | html_url: 'https://github.com/apps/weekly-digest', 176 | }, 177 | created_at: '2018-04-19T00:00:00Z', 178 | updated_at: '2018-04-20T00:00:00Z', 179 | merged_at: '2018-04-21T00:00:00Z', 180 | }, 181 | { 182 | html_url: 'https://github.com/abhijeetps/playground/pull/22', 183 | number: 22, 184 | state: 'closed', 185 | title: 'Weekly Digest test22', 186 | user: { 187 | login: 'abhijeetps', 188 | html_url: 'https://github.com/abhijeetps', 189 | }, 190 | created_at: '2018-04-19T00:00:00Z', 191 | updated_at: '2018-04-20T00:00:00Z', 192 | merged_at: null, 193 | }, 194 | { 195 | html_url: 'https://github.com/abhijeetps/playground/pull/21', 196 | number: 21, 197 | state: 'closed', 198 | title: 'Weekly Digest test21', 199 | user: { 200 | login: 'weekly-digest[bot]', 201 | html_url: 'https://github.com/apps/weekly-digest', 202 | }, 203 | created_at: '2018-04-19T00:00:00Z', 204 | updated_at: '2018-04-20T00:00:00Z', 205 | merged_at: null, 206 | }, 207 | { 208 | html_url: 'https://github.com/abhijeetps/playground/pull/20', 209 | number: 20, 210 | state: 'closed', 211 | title: 'Weekly Digest test20', 212 | user: { 213 | login: 'abhijeetps', 214 | html_url: 'https://github.com/abhijeetps', 215 | }, 216 | created_at: '2018-04-20T00:00:00Z', 217 | updated_at: '2018-04-20T00:00:00Z', 218 | merged_at: null, 219 | }, 220 | { 221 | html_url: 'https://github.com/abhijeetps/playground/pull/19', 222 | number: 19, 223 | state: 'closed', 224 | title: 'Weekly Digest test19', 225 | user: { 226 | login: 'weekly-digest[bot]', 227 | html_url: 'https://github.com/app/weekly-digest', 228 | }, 229 | created_at: '2018-04-20T00:00:00Z', 230 | updated_at: '2018-04-20T00:00:00Z', 231 | merged_at: null, 232 | }, 233 | { 234 | html_url: 'https://github.com/abhijeetps/playground/pull/18', 235 | number: 18, 236 | state: 'open', 237 | title: 'Weekly Digest test18', 238 | user: { 239 | login: 'abhijeetps', 240 | html_url: 'https://github.com/abhijeetps', 241 | }, 242 | created_at: '2018-04-19T00:00:00Z', 243 | updated_at: '2018-04-20T00:00:00Z', 244 | merged_at: '2018-04-21T00:00:00Z', 245 | }, 246 | { 247 | html_url: 'https://github.com/abhijeetps/playground/pull/17', 248 | number: 17, 249 | state: 'open', 250 | title: 'Weekly Digest test17', 251 | user: { 252 | login: 'weekly-digest[bot]', 253 | html_url: 'https://github.com/app/weekly-digest', 254 | }, 255 | created_at: '2018-04-19T00:00:00Z', 256 | updated_at: '2018-04-20T00:00:00Z', 257 | merged_at: '2018-04-21T00:00:00Z', 258 | }, 259 | { 260 | html_url: 'https://github.com/abhijeetps/playground/pull/15', 261 | number: 15, 262 | state: 'open', 263 | title: 'Weekly Digest test15', 264 | user: { 265 | login: 'weekly-digest[bot]', 266 | html_url: 'https://github.com/app/weekly-digest', 267 | }, 268 | created_at: '2018-04-19T00:00:00Z', 269 | updated_at: '2018-04-20T00:00:00Z', 270 | merged_at: null, 271 | }, 272 | { 273 | html_url: 'https://github.com/abhijeetps/playground/pull/13', 274 | number: 13, 275 | state: 'open', 276 | title: 'Weekly Digest test13', 277 | user: { 278 | login: 'weekly-digest[bot]', 279 | html_url: 'https://github.com/app/weekly-digest', 280 | }, 281 | created_at: '2018-04-20T00:00:00Z', 282 | updated_at: '2018-04-20T00:00:00Z', 283 | merged_at: null, 284 | }, 285 | // old 286 | { 287 | html_url: 'https://github.com/abhijeetps/playground/pull/12', 288 | number: 12, 289 | state: 'closed', 290 | title: 'Weekly Digest test12', 291 | user: { 292 | login: 'abhijeetps', 293 | html_url: 'https://github.com/abhijeetps', 294 | }, 295 | created_at: '2018-04-14T00:00:00Z', 296 | updated_at: '2018-04-15T00:00:00Z', 297 | merged_at: '2018-04-16T00:00:00Z', 298 | }, 299 | { 300 | html_url: 'https://github.com/abhijeetps/playground/pull/11', 301 | number: 11, 302 | state: 'closed', 303 | title: 'Weekly Digest test11', 304 | user: { 305 | login: 'weekly-digest[bot]', 306 | html_url: 'https://github.com/apps/weekly-digest', 307 | }, 308 | created_at: '2018-04-14T00:00:00Z', 309 | updated_at: '2018-04-15T00:00:00Z', 310 | merged_at: '2018-04-16T00:00:00Z', 311 | }, 312 | { 313 | html_url: 'https://github.com/abhijeetps/playground/pull/10', 314 | number: 10, 315 | state: 'closed', 316 | title: 'Weekly Digest test10', 317 | user: { 318 | login: 'abhijeetps', 319 | html_url: 'https://github.com/abhijeetps', 320 | }, 321 | created_at: '2018-04-14T00:00:00Z', 322 | updated_at: '2018-04-15T00:00:00Z', 323 | merged_at: null, 324 | }, 325 | { 326 | html_url: 'https://github.com/abhijeetps/playground/pull/9', 327 | number: 9, 328 | state: 'closed', 329 | title: 'Weekly Digest test9', 330 | user: { 331 | login: 'weekly-digest[bot]', 332 | html_url: 'https://github.com/apps/weekly-digest', 333 | }, 334 | created_at: '2018-04-14T00:00:00Z', 335 | updated_at: '2018-04-15T00:00:00Z', 336 | merged_at: null, 337 | }, 338 | { 339 | html_url: 'https://github.com/abhijeetps/playground/pull/8', 340 | number: 8, 341 | state: 'closed', 342 | title: 'Weekly Digest test8', 343 | user: { 344 | login: 'abhijeetps', 345 | html_url: 'https://github.com/abhijeetps', 346 | }, 347 | created_at: '2018-04-16T00:00:00Z', 348 | updated_at: '2018-04-16T00:00:00Z', 349 | merged_at: null, 350 | }, 351 | { 352 | html_url: 'https://github.com/abhijeetps/playground/pull/7', 353 | number: 7, 354 | state: 'closed', 355 | title: 'Weekly Digest test7', 356 | user: { 357 | login: 'weekly-digest[bot]', 358 | html_url: 'https://github.com/app/weekly-digest', 359 | }, 360 | created_at: '2018-04-16T00:00:00Z', 361 | updated_at: '2018-04-16T00:00:00Z', 362 | merged_at: null, 363 | }, 364 | { 365 | html_url: 'https://github.com/abhijeetps/playground/pull/6', 366 | number: 6, 367 | state: 'open', 368 | title: 'Weekly Digest test6', 369 | user: { 370 | login: 'abhijeetps', 371 | html_url: 'https://github.com/abhijeetps', 372 | }, 373 | created_at: '2018-04-14T00:00:00Z', 374 | updated_at: '2018-04-15T00:00:00Z', 375 | merged_at: '2018-04-16T00:00:00Z', 376 | }, 377 | { 378 | html_url: 'https://github.com/abhijeetps/playground/pull/5', 379 | number: 5, 380 | state: 'open', 381 | title: 'Weekly Digest test5', 382 | user: { 383 | login: 'weekly-digest[bot]', 384 | html_url: 'https://github.com/app/weekly-digest', 385 | }, 386 | created_at: '2018-04-14T00:00:00Z', 387 | updated_at: '2018-04-15T00:00:00Z', 388 | merged_at: '2018-04-16T00:00:00Z', 389 | }, 390 | { 391 | html_url: 'https://github.com/abhijeetps/playground/pull/4', 392 | number: 4, 393 | state: 'open', 394 | title: 'Weekly Digest test4', 395 | user: { 396 | login: 'abhijeetps', 397 | html_url: 'https://github.com/abhijeetps', 398 | }, 399 | created_at: '2018-04-15T00:00:00Z', 400 | updated_at: '2018-04-16T00:00:00Z', 401 | merged_at: null, 402 | }, 403 | { 404 | html_url: 'https://github.com/abhijeetps/playground/pull/3', 405 | number: 3, 406 | state: 'open', 407 | title: 'Weekly Digest test3', 408 | user: { 409 | login: 'weekly-digest[bot]', 410 | html_url: 'https://github.com/app/weekly-digest', 411 | }, 412 | created_at: '2018-04-15T00:00:00Z', 413 | updated_at: '2018-04-16T00:00:00Z', 414 | merged_at: null, 415 | }, 416 | { 417 | html_url: 'https://github.com/abhijeetps/playground/pull/2', 418 | number: 2, 419 | state: 'open', 420 | title: 'Weekly Digest test2', 421 | user: { 422 | login: 'abhijeetps', 423 | html_url: 'https://github.com/abhijeetps', 424 | }, 425 | created_at: '2018-04-16T00:00:00Z', 426 | updated_at: '2018-04-16T00:00:00Z', 427 | merged_at: null, 428 | }, 429 | { 430 | html_url: 'https://github.com/abhijeetps/playground/pull/1', 431 | number: 1, 432 | state: 'open', 433 | title: 'Weekly Digest test1', 434 | user: { 435 | login: 'weekly-digest[bot]', 436 | html_url: 'https://github.com/app/weekly-digest', 437 | }, 438 | created_at: '2018-04-16T00:00:00Z', 439 | updated_at: '2018-04-16T00:00:00Z', 440 | merged_at: null, 441 | }, 442 | ], 443 | }, 444 | onePullRequest: { 445 | data: [ 446 | { 447 | html_url: 'https://github.com/abhijeetps/playground/pull/32', 448 | number: 32, 449 | state: 'closed', 450 | title: 'Weekly Digest test32', 451 | user: { 452 | login: 'abhijeetps', 453 | html_url: 'https://github.com/abhijeetps', 454 | }, 455 | created_at: '2018-04-24T00:00:00Z', 456 | updated_at: '2018-04-24T00:00:00Z', 457 | merged_at: null, 458 | }, 459 | { 460 | html_url: 'https://github.com/abhijeetps/playground/pull/31', 461 | number: 31, 462 | state: 'closed', 463 | title: 'Weekly Digest test31', 464 | user: { 465 | login: 'weekly-digest[bot]', 466 | html_url: 'https://github.com/app/weekly-digest', 467 | }, 468 | created_at: '2018-04-24T00:00:00Z', 469 | updated_at: '2018-04-24T00:00:00Z', 470 | merged_at: null, 471 | }, 472 | { 473 | html_url: 'https://github.com/abhijeetps/playground/pull/26', 474 | number: 26, 475 | state: 'open', 476 | title: 'Weekly Digest test26', 477 | user: { 478 | login: 'abhijeetps', 479 | html_url: 'https://github.com/abhijeetps', 480 | }, 481 | created_at: '2018-04-24T00:00:00Z', 482 | updated_at: '2018-04-24T00:00:00Z', 483 | merged_at: null, 484 | }, 485 | { 486 | html_url: 'https://github.com/abhijeetps/playground/pull/25', 487 | number: 25, 488 | state: 'open', 489 | title: 'Weekly Digest test25', 490 | user: { 491 | login: 'weekly-digest[bot]', 492 | html_url: 'https://github.com/app/weekly-digest', 493 | }, 494 | created_at: '2018-04-24T00:00:00Z', 495 | updated_at: '2018-04-24T00:00:00Z', 496 | merged_at: null, 497 | }, 498 | // current 499 | { 500 | html_url: 'https://github.com/abhijeetps/playground/pull/20', 501 | number: 20, 502 | state: 'closed', 503 | title: 'Weekly Digest test20', 504 | user: { 505 | login: 'abhijeetps', 506 | html_url: 'https://github.com/abhijeetps', 507 | }, 508 | created_at: '2018-04-20T00:00:00Z', 509 | updated_at: '2018-04-20T00:00:00Z', 510 | merged_at: null, 511 | }, 512 | { 513 | html_url: 'https://github.com/abhijeetps/playground/pull/19', 514 | number: 19, 515 | state: 'closed', 516 | title: 'Weekly Digest test19', 517 | user: { 518 | login: 'weekly-digest[bot]', 519 | html_url: 'https://github.com/app/weekly-digest', 520 | }, 521 | created_at: '2018-04-20T00:00:00Z', 522 | updated_at: '2018-04-20T00:00:00Z', 523 | merged_at: null, 524 | }, 525 | { 526 | html_url: 'https://github.com/abhijeetps/playground/pull/14', 527 | number: 14, 528 | state: 'open', 529 | title: 'Weekly Digest test14', 530 | user: { 531 | login: 'abhijeetps', 532 | html_url: 'https://github.com/abhijeetps', 533 | }, 534 | created_at: '2018-04-20T00:00:00Z', 535 | updated_at: '2018-04-20T00:00:00Z', 536 | merged_at: null, 537 | }, 538 | { 539 | html_url: 'https://github.com/abhijeetps/playground/pull/13', 540 | number: 13, 541 | state: 'open', 542 | title: 'Weekly Digest test13', 543 | user: { 544 | login: 'weekly-digest[bot]', 545 | html_url: 'https://github.com/app/weekly-digest', 546 | }, 547 | created_at: '2018-04-20T00:00:00Z', 548 | updated_at: '2018-04-20T00:00:00Z', 549 | merged_at: null, 550 | }, 551 | // old 552 | { 553 | html_url: 'https://github.com/abhijeetps/playground/pull/8', 554 | number: 8, 555 | state: 'closed', 556 | title: 'Weekly Digest test8', 557 | user: { 558 | login: 'abhijeetps', 559 | html_url: 'https://github.com/abhijeetps', 560 | }, 561 | created_at: '2018-04-16T00:00:00Z', 562 | updated_at: '2018-04-16T00:00:00Z', 563 | merged_at: null, 564 | }, 565 | { 566 | html_url: 'https://github.com/abhijeetps/playground/pull/7', 567 | number: 7, 568 | state: 'closed', 569 | title: 'Weekly Digest test7', 570 | user: { 571 | login: 'weekly-digest[bot]', 572 | html_url: 'https://github.com/app/weekly-digest', 573 | }, 574 | created_at: '2018-04-16T00:00:00Z', 575 | updated_at: '2018-04-16T00:00:00Z', 576 | merged_at: null, 577 | }, 578 | { 579 | html_url: 'https://github.com/abhijeetps/playground/pull/2', 580 | number: 2, 581 | state: 'open', 582 | title: 'Weekly Digest test2', 583 | user: { 584 | login: 'abhijeetps', 585 | html_url: 'https://github.com/abhijeetps', 586 | }, 587 | created_at: '2018-04-16T00:00:00Z', 588 | updated_at: '2018-04-16T00:00:00Z', 589 | merged_at: null, 590 | }, 591 | { 592 | html_url: 'https://github.com/abhijeetps/playground/pull/1', 593 | number: 1, 594 | state: 'open', 595 | title: 'Weekly Digest test1', 596 | user: { 597 | login: 'weekly-digest[bot]', 598 | html_url: 'https://github.com/app/weekly-digest', 599 | }, 600 | created_at: '2018-04-16T00:00:00Z', 601 | updated_at: '2018-04-16T00:00:00Z', 602 | merged_at: null, 603 | }, 604 | ], 605 | }, 606 | openPullRequest: { 607 | data: [ 608 | { 609 | html_url: 'https://github.com/abhijeetps/playground/pull/32', 610 | number: 32, 611 | state: 'closed', 612 | title: 'Weekly Digest test32', 613 | user: { 614 | login: 'abhijeetps', 615 | html_url: 'https://github.com/abhijeetps', 616 | }, 617 | created_at: '2018-04-24T00:00:00Z', 618 | updated_at: '2018-04-24T00:00:00Z', 619 | merged_at: null, 620 | }, 621 | { 622 | html_url: 'https://github.com/abhijeetps/playground/pull/31', 623 | number: 31, 624 | state: 'closed', 625 | title: 'Weekly Digest test31', 626 | user: { 627 | login: 'weekly-digest[bot]', 628 | html_url: 'https://github.com/app/weekly-digest', 629 | }, 630 | created_at: '2018-04-24T00:00:00Z', 631 | updated_at: '2018-04-24T00:00:00Z', 632 | merged_at: null, 633 | }, 634 | { 635 | html_url: 'https://github.com/abhijeetps/playground/pull/26', 636 | number: 26, 637 | state: 'open', 638 | title: 'Weekly Digest test26', 639 | user: { 640 | login: 'abhijeetps', 641 | html_url: 'https://github.com/abhijeetps', 642 | }, 643 | created_at: '2018-04-24T00:00:00Z', 644 | updated_at: '2018-04-24T00:00:00Z', 645 | merged_at: null, 646 | }, 647 | { 648 | html_url: 'https://github.com/abhijeetps/playground/pull/25', 649 | number: 25, 650 | state: 'open', 651 | title: 'Weekly Digest test25', 652 | user: { 653 | login: 'weekly-digest[bot]', 654 | html_url: 'https://github.com/app/weekly-digest', 655 | }, 656 | created_at: '2018-04-24T00:00:00Z', 657 | updated_at: '2018-04-24T00:00:00Z', 658 | merged_at: null, 659 | }, 660 | // current 661 | { 662 | html_url: 'https://github.com/abhijeetps/playground/pull/20', 663 | number: 20, 664 | state: 'closed', 665 | title: 'Weekly Digest test20', 666 | user: { 667 | login: 'abhijeetps', 668 | html_url: 'https://github.com/abhijeetps', 669 | }, 670 | created_at: '2018-04-20T00:00:00Z', 671 | updated_at: '2018-04-20T00:00:00Z', 672 | merged_at: null, 673 | }, 674 | { 675 | html_url: 'https://github.com/abhijeetps/playground/pull/19', 676 | number: 19, 677 | state: 'closed', 678 | title: 'Weekly Digest test19', 679 | user: { 680 | login: 'weekly-digest[bot]', 681 | html_url: 'https://github.com/app/weekly-digest', 682 | }, 683 | created_at: '2018-04-20T00:00:00Z', 684 | updated_at: '2018-04-20T00:00:00Z', 685 | merged_at: null, 686 | }, 687 | { 688 | html_url: 'https://github.com/abhijeetps/playground/pull/15', 689 | number: 15, 690 | state: 'open', 691 | title: 'Weekly Digest test15', 692 | user: { 693 | login: 'abhijeetps', 694 | html_url: 'https://github.com/abhijeetps', 695 | }, 696 | created_at: '2018-04-21T00:00:00Z', 697 | updated_at: '2018-04-21T00:00:00Z', 698 | merged_at: null, 699 | }, 700 | { 701 | html_url: 'https://github.com/abhijeetps/playground/pull/14', 702 | number: 14, 703 | state: 'open', 704 | title: 'Weekly Digest test14', 705 | user: { 706 | login: 'abhijeetps', 707 | html_url: 'https://github.com/abhijeetps', 708 | }, 709 | created_at: '2018-04-20T00:00:00Z', 710 | updated_at: '2018-04-20T00:00:00Z', 711 | merged_at: null, 712 | }, 713 | { 714 | html_url: 'https://github.com/abhijeetps/playground/pull/13', 715 | number: 13, 716 | state: 'open', 717 | title: 'Weekly Digest test13', 718 | user: { 719 | login: 'weekly-digest[bot]', 720 | html_url: 'https://github.com/app/weekly-digest', 721 | }, 722 | created_at: '2018-04-20T00:00:00Z', 723 | updated_at: '2018-04-20T00:00:00Z', 724 | merged_at: null, 725 | }, 726 | // old 727 | { 728 | html_url: 'https://github.com/abhijeetps/playground/pull/8', 729 | number: 8, 730 | state: 'closed', 731 | title: 'Weekly Digest test8', 732 | user: { 733 | login: 'abhijeetps', 734 | html_url: 'https://github.com/abhijeetps', 735 | }, 736 | created_at: '2018-04-16T00:00:00Z', 737 | updated_at: '2018-04-16T00:00:00Z', 738 | merged_at: null, 739 | }, 740 | { 741 | html_url: 'https://github.com/abhijeetps/playground/pull/7', 742 | number: 7, 743 | state: 'closed', 744 | title: 'Weekly Digest test7', 745 | user: { 746 | login: 'weekly-digest[bot]', 747 | html_url: 'https://github.com/app/weekly-digest', 748 | }, 749 | created_at: '2018-04-16T00:00:00Z', 750 | updated_at: '2018-04-16T00:00:00Z', 751 | merged_at: null, 752 | }, 753 | { 754 | html_url: 'https://github.com/abhijeetps/playground/pull/2', 755 | number: 2, 756 | state: 'open', 757 | title: 'Weekly Digest test2', 758 | user: { 759 | login: 'abhijeetps', 760 | html_url: 'https://github.com/abhijeetps', 761 | }, 762 | created_at: '2018-04-16T00:00:00Z', 763 | updated_at: '2018-04-16T00:00:00Z', 764 | merged_at: null, 765 | }, 766 | { 767 | html_url: 'https://github.com/abhijeetps/playground/pull/1', 768 | number: 1, 769 | state: 'open', 770 | title: 'Weekly Digest test1', 771 | user: { 772 | login: 'weekly-digest[bot]', 773 | html_url: 'https://github.com/app/weekly-digest', 774 | }, 775 | created_at: '2018-04-16T00:00:00Z', 776 | updated_at: '2018-04-16T00:00:00Z', 777 | merged_at: null, 778 | }, 779 | ], 780 | }, 781 | updatedPullRequest: { 782 | data: [ 783 | { 784 | html_url: 'https://github.com/abhijeetps/playground/pull/34', 785 | number: 34, 786 | state: 'closed', 787 | title: 'Weekly Digest test34', 788 | user: { 789 | login: 'abhijeetps', 790 | html_url: 'https://github.com/abhijeetps', 791 | }, 792 | created_at: '2018-04-24T00:00:00Z', 793 | updated_at: '2018-04-25T00:00:00Z', 794 | merged_at: null, 795 | }, 796 | { 797 | html_url: 'https://github.com/abhijeetps/playground/pull/33', 798 | number: 33, 799 | state: 'closed', 800 | title: 'Weekly Digest test33', 801 | user: { 802 | login: 'weekly-digest[bot]', 803 | html_url: 'https://github.com/apps/weekly-digest', 804 | }, 805 | created_at: '2018-04-24T00:00:00Z', 806 | updated_at: '2018-04-25T00:00:00Z', 807 | merged_at: null, 808 | }, 809 | { 810 | html_url: 'https://github.com/abhijeetps/playground/pull/28', 811 | number: 28, 812 | state: 'open', 813 | title: 'Weekly Digest test28', 814 | user: { 815 | login: 'abhijeetps', 816 | html_url: 'https://github.com/abhijeetps', 817 | }, 818 | created_at: '2018-04-24T00:00:00Z', 819 | updated_at: '2018-04-25T00:00:00Z', 820 | merged_at: null, 821 | }, 822 | { 823 | html_url: 'https://github.com/abhijeetps/playground/pull/27', 824 | number: 27, 825 | state: 'open', 826 | title: 'Weekly Digest test27', 827 | user: { 828 | login: 'weekly-digest[bot]', 829 | html_url: 'https://github.com/app/weekly-digest', 830 | }, 831 | created_at: '2018-04-24T00:00:00Z', 832 | updated_at: '2018-04-25T00:00:00Z', 833 | merged_at: null, 834 | }, 835 | // current 836 | { 837 | html_url: 'https://github.com/abhijeetps/playground/pull/22', 838 | number: 22, 839 | state: 'closed', 840 | title: 'Weekly Digest test22', 841 | user: { 842 | login: 'abhijeetps', 843 | html_url: 'https://github.com/abhijeetps', 844 | }, 845 | created_at: '2018-04-19T00:00:00Z', 846 | updated_at: '2018-04-20T00:00:00Z', 847 | merged_at: null, 848 | }, 849 | { 850 | html_url: 'https://github.com/abhijeetps/playground/pull/21', 851 | number: 21, 852 | state: 'closed', 853 | title: 'Weekly Digest test21', 854 | user: { 855 | login: 'weekly-digest[bot]', 856 | html_url: 'https://github.com/apps/weekly-digest', 857 | }, 858 | created_at: '2018-04-19T00:00:00Z', 859 | updated_at: '2018-04-20T00:00:00Z', 860 | merged_at: null, 861 | }, 862 | { 863 | html_url: 'https://github.com/abhijeetps/playground/pull/17', 864 | number: 17, 865 | state: 'open', 866 | title: 'Weekly Digest test17', 867 | user: { 868 | login: 'abhijeetps', 869 | html_url: 'https://github.com/abhijeetps', 870 | }, 871 | created_at: '2018-04-19T00:00:00Z', 872 | updated_at: '2018-04-20T00:00:00Z', 873 | merged_at: null, 874 | }, 875 | { 876 | html_url: 'https://github.com/abhijeetps/playground/pull/16', 877 | number: 16, 878 | state: 'open', 879 | title: 'Weekly Digest test16', 880 | user: { 881 | login: 'abhijeetps', 882 | html_url: 'https://github.com/abhijeetps', 883 | }, 884 | created_at: '2018-04-19T00:00:00Z', 885 | updated_at: '2018-04-20T00:00:00Z', 886 | merged_at: null, 887 | }, 888 | { 889 | html_url: 'https://github.com/abhijeetps/playground/pull/15', 890 | number: 15, 891 | state: 'open', 892 | title: 'Weekly Digest test15', 893 | user: { 894 | login: 'weekly-digest[bot]', 895 | html_url: 'https://github.com/app/weekly-digest', 896 | }, 897 | created_at: '2018-04-19T00:00:00Z', 898 | updated_at: '2018-04-20T00:00:00Z', 899 | merged_at: null, 900 | }, 901 | // old 902 | { 903 | html_url: 'https://github.com/abhijeetps/playground/pull/10', 904 | number: 10, 905 | state: 'closed', 906 | title: 'Weekly Digest test10', 907 | user: { 908 | login: 'abhijeetps', 909 | html_url: 'https://github.com/abhijeetps', 910 | }, 911 | created_at: '2018-04-14T00:00:00Z', 912 | updated_at: '2018-04-15T00:00:00Z', 913 | merged_at: null, 914 | }, 915 | { 916 | html_url: 'https://github.com/abhijeetps/playground/pull/9', 917 | number: 9, 918 | state: 'closed', 919 | title: 'Weekly Digest test9', 920 | user: { 921 | login: 'weekly-digest[bot]', 922 | html_url: 'https://github.com/apps/weekly-digest', 923 | }, 924 | created_at: '2018-04-14T00:00:00Z', 925 | updated_at: '2018-04-15T00:00:00Z', 926 | merged_at: null, 927 | }, 928 | { 929 | html_url: 'https://github.com/abhijeetps/playground/pull/4', 930 | number: 4, 931 | state: 'open', 932 | title: 'Weekly Digest test4', 933 | user: { 934 | login: 'abhijeetps', 935 | html_url: 'https://github.com/abhijeetps', 936 | }, 937 | created_at: '2018-04-15T00:00:00Z', 938 | updated_at: '2018-04-16T00:00:00Z', 939 | merged_at: null, 940 | }, 941 | { 942 | html_url: 'https://github.com/abhijeetps/playground/pull/3', 943 | number: 3, 944 | state: 'open', 945 | title: 'Weekly Digest test3', 946 | user: { 947 | login: 'weekly-digest[bot]', 948 | html_url: 'https://github.com/app/weekly-digest', 949 | }, 950 | created_at: '2018-04-15T00:00:00Z', 951 | updated_at: '2018-04-16T00:00:00Z', 952 | merged_at: null, 953 | }, 954 | ], 955 | }, 956 | mergedPullRequest: { 957 | data: [ 958 | { 959 | html_url: 'https://github.com/abhijeetps/playground/pull/36', 960 | number: 36, 961 | state: 'closed', 962 | title: 'Weekly Digest test36', 963 | user: { 964 | login: 'abhijeetps', 965 | html_url: 'https://github.com/abhijeetps', 966 | }, 967 | created_at: '2018-04-24T00:00:00Z', 968 | updated_at: '2018-04-25T00:00:00Z', 969 | merged_at: '2018-04-26T00:00:00Z', 970 | }, 971 | { 972 | html_url: 'https://github.com/abhijeetps/playground/pull/35', 973 | number: 35, 974 | state: 'closed', 975 | title: 'Weekly Digest test35', 976 | user: { 977 | login: 'weekly-digest[bot]', 978 | html_url: 'https://github.com/apps/weekly-digest', 979 | }, 980 | created_at: '2018-04-24T00:00:00Z', 981 | updated_at: '2018-04-25T00:00:00Z', 982 | merged_at: '2018-04-26T00:00:00Z', 983 | }, 984 | { 985 | html_url: 'https://github.com/abhijeetps/playground/pull/30', 986 | number: 30, 987 | state: 'open', 988 | title: 'Weekly Digest test30', 989 | user: { 990 | login: 'abhijeetps', 991 | html_url: 'https://github.com/abhijeetps', 992 | }, 993 | created_at: '2018-04-24T00:00:00Z', 994 | updated_at: '2018-04-25T00:00:00Z', 995 | merged_at: '2018-04-26T00:00:00Z', 996 | }, 997 | { 998 | html_url: 'https://github.com/abhijeetps/playground/pull/29', 999 | number: 29, 1000 | state: 'open', 1001 | title: 'Weekly Digest test29', 1002 | user: { 1003 | login: 'weekly-digest[bot]', 1004 | html_url: 'https://github.com/app/weekly-digest', 1005 | }, 1006 | created_at: '2018-04-24T00:00:00Z', 1007 | updated_at: '2018-04-25T00:00:00Z', 1008 | merged_at: '2018-04-26T00:00:00Z', 1009 | }, 1010 | // current 1011 | { 1012 | html_url: 'https://github.com/abhijeetps/playground/pull/25', 1013 | number: 25, 1014 | state: 'closed', 1015 | title: 'Weekly Digest test25', 1016 | user: { 1017 | login: 'abhijeetps', 1018 | html_url: 'https://github.com/abhijeetps', 1019 | }, 1020 | created_at: '2018-04-20T00:00:00Z', 1021 | updated_at: '2018-04-21T00:00:00Z', 1022 | merged_at: '2018-04-22T00:00:00Z', 1023 | }, 1024 | { 1025 | html_url: 'https://github.com/abhijeetps/playground/pull/24', 1026 | number: 24, 1027 | state: 'closed', 1028 | title: 'Weekly Digest test24', 1029 | user: { 1030 | login: 'abhijeetps', 1031 | html_url: 'https://github.com/abhijeetps', 1032 | }, 1033 | created_at: '2018-04-19T00:00:00Z', 1034 | updated_at: '2018-04-20T00:00:00Z', 1035 | merged_at: '2018-04-21T00:00:00Z', 1036 | }, 1037 | { 1038 | html_url: 'https://github.com/abhijeetps/playground/pull/23', 1039 | number: 23, 1040 | state: 'closed', 1041 | title: 'Weekly Digest test23', 1042 | user: { 1043 | login: 'weekly-digest[bot]', 1044 | html_url: 'https://github.com/apps/weekly-digest', 1045 | }, 1046 | created_at: '2018-04-19T00:00:00Z', 1047 | updated_at: '2018-04-20T00:00:00Z', 1048 | merged_at: '2018-04-21T00:00:00Z', 1049 | }, 1050 | { 1051 | html_url: 'https://github.com/abhijeetps/playground/pull/18', 1052 | number: 18, 1053 | state: 'open', 1054 | title: 'Weekly Digest test18', 1055 | user: { 1056 | login: 'abhijeetps', 1057 | html_url: 'https://github.com/abhijeetps', 1058 | }, 1059 | created_at: '2018-04-19T00:00:00Z', 1060 | updated_at: '2018-04-20T00:00:00Z', 1061 | merged_at: '2018-04-21T00:00:00Z', 1062 | }, 1063 | { 1064 | html_url: 'https://github.com/abhijeetps/playground/pull/17', 1065 | number: 17, 1066 | state: 'open', 1067 | title: 'Weekly Digest test17', 1068 | user: { 1069 | login: 'weekly-digest[bot]', 1070 | html_url: 'https://github.com/app/weekly-digest', 1071 | }, 1072 | created_at: '2018-04-19T00:00:00Z', 1073 | updated_at: '2018-04-20T00:00:00Z', 1074 | merged_at: '2018-04-21T00:00:00Z', 1075 | }, 1076 | // old 1077 | { 1078 | html_url: 'https://github.com/abhijeetps/playground/pull/12', 1079 | number: 12, 1080 | state: 'closed', 1081 | title: 'Weekly Digest test12', 1082 | user: { 1083 | login: 'abhijeetps', 1084 | html_url: 'https://github.com/abhijeetps', 1085 | }, 1086 | created_at: '2018-04-14T00:00:00Z', 1087 | updated_at: '2018-04-15T00:00:00Z', 1088 | merged_at: '2018-04-16T00:00:00Z', 1089 | }, 1090 | { 1091 | html_url: 'https://github.com/abhijeetps/playground/pull/11', 1092 | number: 11, 1093 | state: 'closed', 1094 | title: 'Weekly Digest test11', 1095 | user: { 1096 | login: 'weekly-digest[bot]', 1097 | html_url: 'https://github.com/apps/weekly-digest', 1098 | }, 1099 | created_at: '2018-04-14T00:00:00Z', 1100 | updated_at: '2018-04-15T00:00:00Z', 1101 | merged_at: '2018-04-16T00:00:00Z', 1102 | }, 1103 | { 1104 | html_url: 'https://github.com/abhijeetps/playground/pull/6', 1105 | number: 6, 1106 | state: 'open', 1107 | title: 'Weekly Digest test6', 1108 | user: { 1109 | login: 'abhijeetps', 1110 | html_url: 'https://github.com/abhijeetps', 1111 | }, 1112 | created_at: '2018-04-14T00:00:00Z', 1113 | updated_at: '2018-04-15T00:00:00Z', 1114 | merged_at: '2018-04-16T00:00:00Z', 1115 | }, 1116 | { 1117 | html_url: 'https://github.com/abhijeetps/playground/pull/5', 1118 | number: 5, 1119 | state: 'open', 1120 | title: 'Weekly Digest test5', 1121 | user: { 1122 | login: 'weekly-digest[bot]', 1123 | html_url: 'https://github.com/app/weekly-digest', 1124 | }, 1125 | created_at: '2018-04-14T00:00:00Z', 1126 | updated_at: '2018-04-15T00:00:00Z', 1127 | merged_at: '2018-04-16T00:00:00Z', 1128 | }, 1129 | ], 1130 | }, 1131 | allPullRequests: { 1132 | data: [ 1133 | // newer 1134 | { 1135 | html_url: 'https://github.com/abhijeetps/playground/pull/36', 1136 | number: 36, 1137 | state: 'closed', 1138 | title: 'Weekly Digest test36', 1139 | user: { 1140 | login: 'abhijeetps', 1141 | html_url: 'https://github.com/abhijeetps', 1142 | }, 1143 | created_at: '2018-04-24T00:00:00Z', 1144 | updated_at: '2018-04-25T00:00:00Z', 1145 | merged_at: '2018-04-26T00:00:00Z', 1146 | }, 1147 | { 1148 | html_url: 'https://github.com/abhijeetps/playground/pull/35', 1149 | number: 35, 1150 | state: 'closed', 1151 | title: 'Weekly Digest test35', 1152 | user: { 1153 | login: 'weekly-digest[bot]', 1154 | html_url: 'https://github.com/apps/weekly-digest', 1155 | }, 1156 | created_at: '2018-04-24T00:00:00Z', 1157 | updated_at: '2018-04-25T00:00:00Z', 1158 | merged_at: '2018-04-26T00:00:00Z', 1159 | }, 1160 | { 1161 | html_url: 'https://github.com/abhijeetps/playground/pull/34', 1162 | number: 34, 1163 | state: 'closed', 1164 | title: 'Weekly Digest test34', 1165 | user: { 1166 | login: 'abhijeetps', 1167 | html_url: 'https://github.com/abhijeetps', 1168 | }, 1169 | created_at: '2018-04-24T00:00:00Z', 1170 | updated_at: '2018-04-25T00:00:00Z', 1171 | merged_at: null, 1172 | }, 1173 | { 1174 | html_url: 'https://github.com/abhijeetps/playground/pull/33', 1175 | number: 33, 1176 | state: 'closed', 1177 | title: 'Weekly Digest test33', 1178 | user: { 1179 | login: 'weekly-digest[bot]', 1180 | html_url: 'https://github.com/apps/weekly-digest', 1181 | }, 1182 | created_at: '2018-04-24T00:00:00Z', 1183 | updated_at: '2018-04-25T00:00:00Z', 1184 | merged_at: null, 1185 | }, 1186 | { 1187 | html_url: 'https://github.com/abhijeetps/playground/pull/32', 1188 | number: 32, 1189 | state: 'closed', 1190 | title: 'Weekly Digest test32', 1191 | user: { 1192 | login: 'abhijeetps', 1193 | html_url: 'https://github.com/abhijeetps', 1194 | }, 1195 | created_at: '2018-04-24T00:00:00Z', 1196 | updated_at: '2018-04-24T00:00:00Z', 1197 | merged_at: null, 1198 | }, 1199 | { 1200 | html_url: 'https://github.com/abhijeetps/playground/pull/31', 1201 | number: 31, 1202 | state: 'closed', 1203 | title: 'Weekly Digest test31', 1204 | user: { 1205 | login: 'weekly-digest[bot]', 1206 | html_url: 'https://github.com/app/weekly-digest', 1207 | }, 1208 | created_at: '2018-04-24T00:00:00Z', 1209 | updated_at: '2018-04-24T00:00:00Z', 1210 | merged_at: null, 1211 | }, 1212 | { 1213 | html_url: 'https://github.com/abhijeetps/playground/pull/30', 1214 | number: 30, 1215 | state: 'open', 1216 | title: 'Weekly Digest test30', 1217 | user: { 1218 | login: 'abhijeetps', 1219 | html_url: 'https://github.com/abhijeetps', 1220 | }, 1221 | created_at: '2018-04-24T00:00:00Z', 1222 | updated_at: '2018-04-25T00:00:00Z', 1223 | merged_at: '2018-04-26T00:00:00Z', 1224 | }, 1225 | { 1226 | html_url: 'https://github.com/abhijeetps/playground/pull/29', 1227 | number: 29, 1228 | state: 'open', 1229 | title: 'Weekly Digest test29', 1230 | user: { 1231 | login: 'weekly-digest[bot]', 1232 | html_url: 'https://github.com/app/weekly-digest', 1233 | }, 1234 | created_at: '2018-04-24T00:00:00Z', 1235 | updated_at: '2018-04-25T00:00:00Z', 1236 | merged_at: '2018-04-26T00:00:00Z', 1237 | }, 1238 | { 1239 | html_url: 'https://github.com/abhijeetps/playground/pull/28', 1240 | number: 28, 1241 | state: 'open', 1242 | title: 'Weekly Digest test28', 1243 | user: { 1244 | login: 'abhijeetps', 1245 | html_url: 'https://github.com/abhijeetps', 1246 | }, 1247 | created_at: '2018-04-24T00:00:00Z', 1248 | updated_at: '2018-04-25T00:00:00Z', 1249 | merged_at: null, 1250 | }, 1251 | { 1252 | html_url: 'https://github.com/abhijeetps/playground/pull/27', 1253 | number: 27, 1254 | state: 'open', 1255 | title: 'Weekly Digest test27', 1256 | user: { 1257 | login: 'weekly-digest[bot]', 1258 | html_url: 'https://github.com/app/weekly-digest', 1259 | }, 1260 | created_at: '2018-04-24T00:00:00Z', 1261 | updated_at: '2018-04-25T00:00:00Z', 1262 | merged_at: null, 1263 | }, 1264 | { 1265 | html_url: 'https://github.com/abhijeetps/playground/pull/26', 1266 | number: 26, 1267 | state: 'open', 1268 | title: 'Weekly Digest test26', 1269 | user: { 1270 | login: 'abhijeetps', 1271 | html_url: 'https://github.com/abhijeetps', 1272 | }, 1273 | created_at: '2018-04-24T00:00:00Z', 1274 | updated_at: '2018-04-24T00:00:00Z', 1275 | merged_at: null, 1276 | }, 1277 | { 1278 | html_url: 'https://github.com/abhijeetps/playground/pull/25', 1279 | number: 25, 1280 | state: 'open', 1281 | title: 'Weekly Digest test25', 1282 | user: { 1283 | login: 'weekly-digest[bot]', 1284 | html_url: 'https://github.com/app/weekly-digest', 1285 | }, 1286 | created_at: '2018-04-24T00:00:00Z', 1287 | updated_at: '2018-04-24T00:00:00Z', 1288 | merged_at: null, 1289 | }, 1290 | // current 1291 | { 1292 | html_url: 'https://github.com/abhijeetps/playground/pull/24', 1293 | number: 24, 1294 | state: 'closed', 1295 | title: 'Weekly Digest test24', 1296 | user: { 1297 | login: 'abhijeetps', 1298 | html_url: 'https://github.com/abhijeetps', 1299 | }, 1300 | created_at: '2018-04-19T00:00:00Z', 1301 | updated_at: '2018-04-20T00:00:00Z', 1302 | merged_at: '2018-04-21T00:00:00Z', 1303 | }, 1304 | { 1305 | html_url: 'https://github.com/abhijeetps/playground/pull/23', 1306 | number: 23, 1307 | state: 'closed', 1308 | title: 'Weekly Digest test23', 1309 | user: { 1310 | login: 'weekly-digest[bot]', 1311 | html_url: 'https://github.com/apps/weekly-digest', 1312 | }, 1313 | created_at: '2018-04-19T00:00:00Z', 1314 | updated_at: '2018-04-20T00:00:00Z', 1315 | merged_at: '2018-04-21T00:00:00Z', 1316 | }, 1317 | { 1318 | html_url: 'https://github.com/abhijeetps/playground/pull/22', 1319 | number: 22, 1320 | state: 'closed', 1321 | title: 'Weekly Digest test22', 1322 | user: { 1323 | login: 'abhijeetps', 1324 | html_url: 'https://github.com/abhijeetps', 1325 | }, 1326 | created_at: '2018-04-19T00:00:00Z', 1327 | updated_at: '2018-04-20T00:00:00Z', 1328 | merged_at: null, 1329 | }, 1330 | { 1331 | html_url: 'https://github.com/abhijeetps/playground/pull/21', 1332 | number: 21, 1333 | state: 'closed', 1334 | title: 'Weekly Digest test21', 1335 | user: { 1336 | login: 'weekly-digest[bot]', 1337 | html_url: 'https://github.com/apps/weekly-digest', 1338 | }, 1339 | created_at: '2018-04-19T00:00:00Z', 1340 | updated_at: '2018-04-20T00:00:00Z', 1341 | merged_at: null, 1342 | }, 1343 | { 1344 | html_url: 'https://github.com/abhijeetps/playground/pull/20', 1345 | number: 20, 1346 | state: 'closed', 1347 | title: 'Weekly Digest test20', 1348 | user: { 1349 | login: 'abhijeetps', 1350 | html_url: 'https://github.com/abhijeetps', 1351 | }, 1352 | created_at: '2018-04-20T00:00:00Z', 1353 | updated_at: '2018-04-20T00:00:00Z', 1354 | merged_at: null, 1355 | }, 1356 | { 1357 | html_url: 'https://github.com/abhijeetps/playground/pull/19', 1358 | number: 19, 1359 | state: 'closed', 1360 | title: 'Weekly Digest test19', 1361 | user: { 1362 | login: 'weekly-digest[bot]', 1363 | html_url: 'https://github.com/app/weekly-digest', 1364 | }, 1365 | created_at: '2018-04-20T00:00:00Z', 1366 | updated_at: '2018-04-20T00:00:00Z', 1367 | merged_at: null, 1368 | }, 1369 | { 1370 | html_url: 'https://github.com/abhijeetps/playground/pull/18', 1371 | number: 18, 1372 | state: 'open', 1373 | title: 'Weekly Digest test18', 1374 | user: { 1375 | login: 'abhijeetps', 1376 | html_url: 'https://github.com/abhijeetps', 1377 | }, 1378 | created_at: '2018-04-19T00:00:00Z', 1379 | updated_at: '2018-04-20T00:00:00Z', 1380 | merged_at: '2018-04-21T00:00:00Z', 1381 | }, 1382 | { 1383 | html_url: 'https://github.com/abhijeetps/playground/pull/17', 1384 | number: 17, 1385 | state: 'open', 1386 | title: 'Weekly Digest test17', 1387 | user: { 1388 | login: 'weekly-digest[bot]', 1389 | html_url: 'https://github.com/app/weekly-digest', 1390 | }, 1391 | created_at: '2018-04-19T00:00:00Z', 1392 | updated_at: '2018-04-20T00:00:00Z', 1393 | merged_at: '2018-04-21T00:00:00Z', 1394 | }, 1395 | { 1396 | html_url: 'https://github.com/abhijeetps/playground/pull/16', 1397 | number: 16, 1398 | state: 'open', 1399 | title: 'Weekly Digest test16', 1400 | user: { 1401 | login: 'abhijeetps', 1402 | html_url: 'https://github.com/abhijeetps', 1403 | }, 1404 | created_at: '2018-04-19T00:00:00Z', 1405 | updated_at: '2018-04-20T00:00:00Z', 1406 | merged_at: null, 1407 | }, 1408 | { 1409 | html_url: 'https://github.com/abhijeetps/playground/pull/15', 1410 | number: 15, 1411 | state: 'open', 1412 | title: 'Weekly Digest test15', 1413 | user: { 1414 | login: 'weekly-digest[bot]', 1415 | html_url: 'https://github.com/app/weekly-digest', 1416 | }, 1417 | created_at: '2018-04-19T00:00:00Z', 1418 | updated_at: '2018-04-20T00:00:00Z', 1419 | merged_at: null, 1420 | }, 1421 | { 1422 | html_url: 'https://github.com/abhijeetps/playground/pull/14', 1423 | number: 14, 1424 | state: 'open', 1425 | title: 'Weekly Digest test14', 1426 | user: { 1427 | login: 'abhijeetps', 1428 | html_url: 'https://github.com/abhijeetps', 1429 | }, 1430 | created_at: '2018-04-20T00:00:00Z', 1431 | updated_at: '2018-04-20T00:00:00Z', 1432 | merged_at: null, 1433 | }, 1434 | { 1435 | html_url: 'https://github.com/abhijeetps/playground/pull/13', 1436 | number: 13, 1437 | state: 'open', 1438 | title: 'Weekly Digest test13', 1439 | user: { 1440 | login: 'weekly-digest[bot]', 1441 | html_url: 'https://github.com/app/weekly-digest', 1442 | }, 1443 | created_at: '2018-04-20T00:00:00Z', 1444 | updated_at: '2018-04-20T00:00:00Z', 1445 | merged_at: null, 1446 | }, 1447 | // old 1448 | { 1449 | html_url: 'https://github.com/abhijeetps/playground/pull/12', 1450 | number: 12, 1451 | state: 'closed', 1452 | title: 'Weekly Digest test12', 1453 | user: { 1454 | login: 'abhijeetps', 1455 | html_url: 'https://github.com/abhijeetps', 1456 | }, 1457 | created_at: '2018-04-14T00:00:00Z', 1458 | updated_at: '2018-04-15T00:00:00Z', 1459 | merged_at: '2018-04-16T00:00:00Z', 1460 | }, 1461 | { 1462 | html_url: 'https://github.com/abhijeetps/playground/pull/11', 1463 | number: 11, 1464 | state: 'closed', 1465 | title: 'Weekly Digest test11', 1466 | user: { 1467 | login: 'weekly-digest[bot]', 1468 | html_url: 'https://github.com/apps/weekly-digest', 1469 | }, 1470 | created_at: '2018-04-14T00:00:00Z', 1471 | updated_at: '2018-04-15T00:00:00Z', 1472 | merged_at: '2018-04-16T00:00:00Z', 1473 | }, 1474 | { 1475 | html_url: 'https://github.com/abhijeetps/playground/pull/10', 1476 | number: 10, 1477 | state: 'closed', 1478 | title: 'Weekly Digest test10', 1479 | user: { 1480 | login: 'abhijeetps', 1481 | html_url: 'https://github.com/abhijeetps', 1482 | }, 1483 | created_at: '2018-04-14T00:00:00Z', 1484 | updated_at: '2018-04-15T00:00:00Z', 1485 | merged_at: null, 1486 | }, 1487 | { 1488 | html_url: 'https://github.com/abhijeetps/playground/pull/9', 1489 | number: 9, 1490 | state: 'closed', 1491 | title: 'Weekly Digest test9', 1492 | user: { 1493 | login: 'weekly-digest[bot]', 1494 | html_url: 'https://github.com/apps/weekly-digest', 1495 | }, 1496 | created_at: '2018-04-14T00:00:00Z', 1497 | updated_at: '2018-04-15T00:00:00Z', 1498 | merged_at: null, 1499 | }, 1500 | { 1501 | html_url: 'https://github.com/abhijeetps/playground/pull/8', 1502 | number: 8, 1503 | state: 'closed', 1504 | title: 'Weekly Digest test8', 1505 | user: { 1506 | login: 'abhijeetps', 1507 | html_url: 'https://github.com/abhijeetps', 1508 | }, 1509 | created_at: '2018-04-16T00:00:00Z', 1510 | updated_at: '2018-04-16T00:00:00Z', 1511 | merged_at: null, 1512 | }, 1513 | { 1514 | html_url: 'https://github.com/abhijeetps/playground/pull/7', 1515 | number: 7, 1516 | state: 'closed', 1517 | title: 'Weekly Digest test7', 1518 | user: { 1519 | login: 'weekly-digest[bot]', 1520 | html_url: 'https://github.com/app/weekly-digest', 1521 | }, 1522 | created_at: '2018-04-16T00:00:00Z', 1523 | updated_at: '2018-04-16T00:00:00Z', 1524 | merged_at: null, 1525 | }, 1526 | { 1527 | html_url: 'https://github.com/abhijeetps/playground/pull/6', 1528 | number: 6, 1529 | state: 'open', 1530 | title: 'Weekly Digest test6', 1531 | user: { 1532 | login: 'abhijeetps', 1533 | html_url: 'https://github.com/abhijeetps', 1534 | }, 1535 | created_at: '2018-04-14T00:00:00Z', 1536 | updated_at: '2018-04-15T00:00:00Z', 1537 | merged_at: '2018-04-16T00:00:00Z', 1538 | }, 1539 | { 1540 | html_url: 'https://github.com/abhijeetps/playground/pull/5', 1541 | number: 5, 1542 | state: 'open', 1543 | title: 'Weekly Digest test5', 1544 | user: { 1545 | login: 'weekly-digest[bot]', 1546 | html_url: 'https://github.com/app/weekly-digest', 1547 | }, 1548 | created_at: '2018-04-14T00:00:00Z', 1549 | updated_at: '2018-04-15T00:00:00Z', 1550 | merged_at: '2018-04-16T00:00:00Z', 1551 | }, 1552 | { 1553 | html_url: 'https://github.com/abhijeetps/playground/pull/4', 1554 | number: 4, 1555 | state: 'open', 1556 | title: 'Weekly Digest test4', 1557 | user: { 1558 | login: 'abhijeetps', 1559 | html_url: 'https://github.com/abhijeetps', 1560 | }, 1561 | created_at: '2018-04-15T00:00:00Z', 1562 | updated_at: '2018-04-16T00:00:00Z', 1563 | merged_at: null, 1564 | }, 1565 | { 1566 | html_url: 'https://github.com/abhijeetps/playground/pull/3', 1567 | number: 3, 1568 | state: 'open', 1569 | title: 'Weekly Digest test3', 1570 | user: { 1571 | login: 'weekly-digest[bot]', 1572 | html_url: 'https://github.com/app/weekly-digest', 1573 | }, 1574 | created_at: '2018-04-15T00:00:00Z', 1575 | updated_at: '2018-04-16T00:00:00Z', 1576 | merged_at: null, 1577 | }, 1578 | { 1579 | html_url: 'https://github.com/abhijeetps/playground/pull/2', 1580 | number: 2, 1581 | state: 'open', 1582 | title: 'Weekly Digest test2', 1583 | user: { 1584 | login: 'abhijeetps', 1585 | html_url: 'https://github.com/abhijeetps', 1586 | }, 1587 | created_at: '2018-04-16T00:00:00Z', 1588 | updated_at: '2018-04-16T00:00:00Z', 1589 | merged_at: null, 1590 | }, 1591 | { 1592 | html_url: 'https://github.com/abhijeetps/playground/pull/1', 1593 | number: 1, 1594 | state: 'open', 1595 | title: 'Weekly Digest test1', 1596 | user: { 1597 | login: 'weekly-digest[bot]', 1598 | html_url: 'https://github.com/app/weekly-digest', 1599 | }, 1600 | created_at: '2018-04-16T00:00:00Z', 1601 | updated_at: '2018-04-16T00:00:00Z', 1602 | merged_at: null, 1603 | }, 1604 | ], 1605 | }, 1606 | }; 1607 | --------------------------------------------------------------------------------