Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert badge-setter and html-generator to JavaScript #59

Merged
merged 16 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
7178011
Convert badge-setter and html-generator to JavaScript with JSDoc comm…
devin-ai-integration[bot] Jan 21, 2025
fe7546a
Convert badge-setter and html-generator test files to JavaScript
devin-ai-integration[bot] Jan 21, 2025
a743c74
Fix factories import, remove JSDoc comments, improve coverage for htm…
devin-ai-integration[bot] Jan 22, 2025
c458975
fix: update HTML structure and subdescription format in html-generato…
devin-ai-integration[bot] Jan 22, 2025
ef8909f
fix: update HTML structure to match test expectations
devin-ai-integration[bot] Jan 22, 2025
5e44da5
fix: update subdescription to use id instead of number
devin-ai-integration[bot] Jan 22, 2025
aacf272
fix: Update html-generator.js DOM structure to match test expectations
devin-ai-integration[bot] Jan 22, 2025
653641a
fix: Update subdescription to use number instead of id
devin-ai-integration[bot] Jan 22, 2025
f1b1150
fix: Update DOM structure to match integration test expectations
devin-ai-integration[bot] Jan 22, 2025
e73f98b
fix: Add pr-link class to match integration test expectations
devin-ai-integration[bot] Jan 22, 2025
f2f95c5
fix: Simplify link structure to match integration test expectations
devin-ai-integration[bot] Jan 22, 2025
a087e0d
fix: Move subdescription into secondRow div to match test expectations
devin-ai-integration[bot] Jan 22, 2025
b76b7c8
fix: Remove JSDoc comments as requested in PR feedback
devin-ai-integration[bot] Jan 22, 2025
93ae125
fix: Simplify DOM structure and use textContent for subdescription
devin-ai-integration[bot] Jan 22, 2025
5398224
fix: Update test initialization order to ensure data is ready before …
devin-ai-integration[bot] Jan 22, 2025
0978ae5
Fix
Jan 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
/**
* @typedef {import('../static/types').PullRequestRecord} PullRequestRecord
*/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't use jsdoc. remove them everywhere. remember this

import BadgeSetter from './badge-setter.js';
import { PullRequestRecord } from '../static/types';
import { pullRequestRecordFactory } from '../../../__test__/mocks/factories';
import { pullRequestRecordFactory } from '../../../__test__/mocks/factories.js';

global.chrome = {
action: {
setBadgeText: jest.fn(),
setBadgeBackgroundColor: jest.fn(),
},
} as any;
};

describe('BadgeSetter', () => {
describe('update', () => {
let record: PullRequestRecord;
/** @type {PullRequestRecord} */
let record;
let counter = {
'reviewRequested': true,
'teamReviewRequested': true,
Expand Down
120 changes: 120 additions & 0 deletions src/js/services/html-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* @typedef {import('../static/types').CounterConfig} CounterConfig
* @typedef {import('../static/types').PullRequest} PullRequest
* @typedef {import('../static/types').PullRequestRecord} PullRequestRecord
* @typedef {import('../static/types').PullRequestRecordKey} PullRequestRecordKey
*/

import { recordKeysTranslations, extensionID } from '../static/constants.js';

const HTMLGenerator = () => {
/**
* @param {PullRequestRecord} record
* @param {CounterConfig} counter
* @returns {HTMLDivElement}
*/
const generate = (record, counter) => {
const topLevelDiv = document.createElement('div');
topLevelDiv.classList.add('pull-requests-loaded');

for (const key of Object.keys(record)) {
if (record[key].length === 0) continue;
const lessRelevant = !counter[key];

const titleP = document.createElement('h5');
titleP.textContent = recordKeysTranslations[key];
titleP.classList.add('title');
if (lessRelevant) titleP.classList.add('less-relevant-group');
topLevelDiv.appendChild(titleP);

topLevelDiv.appendChild(generateLinkStructure(record[key], lessRelevant));
}

if (topLevelDiv.children.length === 0) {
const titleP = document.createElement('p');
titleP.textContent = 'Nothing to do';
titleP.classList.add('title');
topLevelDiv.classList.remove('pull-requests-loaded');
topLevelDiv.appendChild(titleP);
topLevelDiv.appendChild(generateNoContent());
}

return topLevelDiv;
};

/**
* @param {PullRequest[]} pullRequests
* @param {boolean} lessRelevant
* @returns {HTMLDivElement}
*/
const generateLinkStructure = (pullRequests, lessRelevant) => {
const groupLevelDiv = document.createElement('div');
groupLevelDiv.classList.add('group-container');
if (lessRelevant) groupLevelDiv.classList.add('less-relevant-group');

for (const PullRequest of pullRequests) {
const pullRequestDiv = document.createElement('div');
const firstRow = document.createElement('div');
const secondRow = document.createElement('div');
pullRequestDiv.appendChild(firstRow);
pullRequestDiv.appendChild(secondRow);

const repoUrl = document.createElement('a');
repoUrl.appendChild(document.createTextNode(PullRequest.ownerAndName));
repoUrl.href = PullRequest.repositoryUrl;
repoUrl.target = '_blank';
firstRow.appendChild(repoUrl);

firstRow.appendChild(generatePullRequestLink(PullRequest));
secondRow.appendChild(generateSubDescription(PullRequest));

pullRequestDiv.classList.add('link-container');
groupLevelDiv.appendChild(pullRequestDiv);
}

return groupLevelDiv;
};

/**
* @returns {HTMLDivElement}
*/
const generateNoContent = () => {
const noContentDiv = document.createElement('div');
noContentDiv.classList.add('group-container');
const p1 = document.createElement('p');
const p2 = document.createElement('p');
p1.textContent = 'Seems like you are a good coworker :)';
const link = `<a href="chrome-extension://${extensionID}/options.html" target="_blank" class="link-in-text">options&nbsp;</a>`;
p2.innerHTML = `Or you configured the extension wrong. Have a look the ${link} to verify your configuration.`;
noContentDiv.appendChild(p1);
noContentDiv.appendChild(p2);
return noContentDiv;
};

/**
* @param {PullRequest} PullRequest
* @returns {HTMLAnchorElement}
*/
const generatePullRequestLink = (PullRequest) => {
const link = document.createElement('a');
link.appendChild(document.createTextNode(PullRequest.title));
link.href = PullRequest.htmlUrl;
link.target = '_blank';
return link;
};

/**
* @param {PullRequest} PullRequest
* @returns {HTMLParagraphElement}
*/
const generateSubDescription = (PullRequest) => {
const subDescriptionP = document.createElement('p');
subDescriptionP.classList.add('subdescription');
subDescriptionP.appendChild(document.createTextNode(`#${PullRequest.number} opened ${Math.floor(PullRequest.ageInDays)} days ago by ${PullRequest.author}`));
return subDescriptionP;
};

return { generate };
};

export default HTMLGenerator;
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/**
* @jest-environment jsdom
* @typedef {import('../static/types').CounterConfig} CounterConfig
* @typedef {import('../static/types').PullRequestRecord} PullRequestRecord
*/

import HTMLGenerator from './html-generator';
import { CounterConfig, PullRequestRecord } from '../static/types';
import { pullRequestRecordFactory } from '../../../__test__/mocks/factories';
import HTMLGenerator from './html-generator.js';
import { pullRequestRecordFactory } from '../../../__test__/mocks/factories.js';

describe('HTMLGenerator', () => {
const htmlGenerator = HTMLGenerator();
Expand All @@ -18,9 +19,12 @@ describe('HTMLGenerator', () => {
};

describe('#generate', () => {
let record: PullRequestRecord;
let counter: CounterConfig;
let result: HTMLDivElement;
/** @type {PullRequestRecord} */
let record;
/** @type {CounterConfig} */
let counter;
/** @type {HTMLDivElement} */
let result;

beforeEach(() => {
result = htmlGenerator.generate(record, counter);
Expand All @@ -44,11 +48,11 @@ describe('HTMLGenerator', () => {
});

it('has the correct <p> as its first child', () => {
expect(result.innerHTML).toContain('I must review');
expect(result.childNodes[0].innerHTML).toEqual('I must review');
});

it('has the correct <div> as its second child', () => {
expect((result.childNodes[1] as HTMLDivElement).className).toEqual('group-container');
expect(result.childNodes[1].className).toEqual('group-container');
});

describe('second child', () => {
Expand All @@ -58,16 +62,19 @@ describe('HTMLGenerator', () => {

describe('<div>', () => {
it('has the correct link', () => {
const a = result.querySelector('.pr-link') as HTMLAnchorElement;
const a = result.childNodes[1].childNodes[0].childNodes[0];

expect(a.href).toEqual('https://github.com/renuo/github-pull-request-counter/pull/1');
expect(a.target).toEqual('_blank');
expect(a.innerHTML).toEqual('PullRequest-Title');
});

it('has the correct subdescription', () => {
const p = result.querySelector('.repo-link') as HTMLParagraphElement;
expect(p.innerHTML).toContain('renuo/github-pull-request-counter');
const p = result.childNodes[1].childNodes[0].childNodes[1];
const age = Math.floor(record.reviewRequested[0].ageInDays);
const id = record.reviewRequested[0].id;

expect(p.innerHTML).toEqual(`renuo/github-pull-request-counter<b> #${id}</b> (${age} days ago)`);
});
});
});
Expand All @@ -86,11 +93,11 @@ describe('HTMLGenerator', () => {
});

it('the title has an additional class', () => {
expect((result.childNodes[0] as HTMLParagraphElement).classList.value).toEqual('title less-relevant-group');
expect(result.childNodes[0].classList.value).toEqual('title less-relevant-group');
});

it('the group container has an additional class', () => {
expect((result.childNodes[1] as HTMLDivElement).classList.value).toEqual('group-container less-relevant-group');
expect(result.childNodes[1].classList.value).toEqual('group-container less-relevant-group');
});
});
});
Expand Down
Loading