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

report(pwa): add tooltip to badge gauge #6689

Merged
merged 2 commits into from
Dec 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 6 additions & 4 deletions lighthouse-core/report/html/renderer/category-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,14 @@ class CategoryRenderer {

/**
* @param {LH.ReportResult.Category} category
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
* @return {Element}
*/
renderCategoryHeader(category) {
renderCategoryHeader(category, groupDefinitions) {
const tmpl = this.dom.cloneTemplate('#tmpl-lh-category-header', this.templateContext);

const gaugeContainerEl = this.dom.find('.lh-score__gauge', tmpl);
const gaugeEl = this.renderScoreGauge(category);
const gaugeEl = this.renderScoreGauge(category, groupDefinitions);
gaugeContainerEl.appendChild(gaugeEl);

this.dom.find('.lh-category-header__title', tmpl).appendChild(
Expand Down Expand Up @@ -329,9 +330,10 @@ class CategoryRenderer {

/**
* @param {LH.ReportResult.Category} category
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
* @return {DocumentFragment}
*/
renderScoreGauge(category) {
renderScoreGauge(category, groupDefinitions) { // eslint-disable-line no-unused-vars
const tmpl = this.dom.cloneTemplate('#tmpl-lh-gauge', this.templateContext);
const wrapper = /** @type {HTMLAnchorElement} */ (this.dom.find('.lh-gauge__wrapper', tmpl));
wrapper.href = `#${category.id}`;
Expand Down Expand Up @@ -387,7 +389,7 @@ class CategoryRenderer {
render(category, groupDefinitions = {}) {
const element = this.dom.createElement('div', 'lh-category');
this.createPermalinkSpan(element, category.id);
element.appendChild(this.renderCategoryHeader(category));
element.appendChild(this.renderCategoryHeader(category, groupDefinitions));

// Top level clumps for audits, in order they will appear in the report.
/** @type {Map<TopLevelClumpId, Array<LH.ReportResult.AuditRef>>} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
const element = this.dom.createElement('div', 'lh-category');
if (environment === 'PSI') {
const gaugeEl = this.dom.createElement('div', 'lh-score__gauge');
gaugeEl.appendChild(this.renderScoreGauge(category));
gaugeEl.appendChild(this.renderScoreGauge(category, groups));
element.appendChild(gaugeEl);
} else {
this.createPermalinkSpan(element, category.id);
element.appendChild(this.renderCategoryHeader(category));
element.appendChild(this.renderCategoryHeader(category, groups));
}

// Metrics
Expand Down
30 changes: 27 additions & 3 deletions lighthouse-core/report/html/renderer/pwa-category-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class PwaCategoryRenderer extends CategoryRenderer {
render(category, groupDefinitions = {}) {
const categoryElem = this.dom.createElement('div', 'lh-category');
this.createPermalinkSpan(categoryElem, category.id);
categoryElem.appendChild(this.renderCategoryHeader(category));
categoryElem.appendChild(this.renderCategoryHeader(category, groupDefinitions));

const auditRefs = category.auditRefs;

Expand All @@ -48,12 +48,13 @@ class PwaCategoryRenderer extends CategoryRenderer {

/**
* @param {LH.ReportResult.Category} category
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
* @return {DocumentFragment}
*/
renderScoreGauge(category) {
renderScoreGauge(category, groupDefinitions) {
// Defer to parent-gauge style if category error.
if (category.score === null) {
return super.renderScoreGauge(category);
return super.renderScoreGauge(category, groupDefinitions);
}

const tmpl = this.dom.cloneTemplate('#tmpl-lh-gauge--pwa', this.templateContext);
Expand All @@ -73,6 +74,7 @@ class PwaCategoryRenderer extends CategoryRenderer {
}

this.dom.find('.lh-gauge__label', tmpl).textContent = category.title;
wrapper.title = this._getGaugeTooltip(category.auditRefs, groupDefinitions);
return tmpl;
}

Expand Down Expand Up @@ -104,6 +106,28 @@ class PwaCategoryRenderer extends CategoryRenderer {
return uniqueGroupIds;
}

/**
* Returns a tooltip string summarizing group pass rates.
* @param {Array<LH.ReportResult.AuditRef>} auditRefs
* @param {Record<string, LH.Result.ReportGroup>} groupDefinitions
* @return {string}
*/
_getGaugeTooltip(auditRefs, groupDefinitions) {
const groupIds = this._getGroupIds(auditRefs);

const tips = [];
for (const groupId of groupIds) {
const groupAuditRefs = auditRefs.filter(ref => ref.group === groupId);
const auditCount = groupAuditRefs.length;
const passedCount = groupAuditRefs.filter(ref => Util.showAsPassed(ref.result)).length;

const title = groupDefinitions[groupId].title;
tips.push(`${title}: ${passedCount}/${auditCount}`);
}

return tips.join(', ');
}

/**
* Render non-manual audits in groups, giving a badge to any group that has
* all passing audits.
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/report/html/renderer/report-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class ReportRenderer {
const customGauges = [];
for (const category of report.reportCategories) {
const renderer = specificCategoryRenderers[category.id] || categoryRenderer;
const categoryGauge = renderer.renderScoreGauge(category);
const categoryGauge = renderer.renderScoreGauge(category, report.categoryGroups || {});

// Group gauges that aren't default at the end of the header
if (renderer.renderScoreGauge === categoryRenderer.renderScoreGauge) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ describe('PwaCategoryRenderer', () => {

const targetGroupId = groupIds[2];
assert.ok(targetGroupId);
const targetGroupTitle = sampleResults.categoryGroups[targetGroupId].title;
const targetAuditRefs = auditRefs.filter(ref => ref.group === targetGroupId);

// Try every permutation of audit scoring.
Expand All @@ -134,13 +135,25 @@ describe('PwaCategoryRenderer', () => {
const badgedScoreGauge =
categoryElem.querySelector('.lh-gauge--pwa__wrapper[class*="lh-badged--"]');

const tooltip = categoryElem.querySelector('.lh-gauge--pwa__wrapper').title;
const targetGroupTip = tooltip.split(', ').find(tip => tip.startsWith(targetGroupTitle));
assert.ok(targetGroupTip);

// Only expect a badge (and badged gauge) on last permutation (all bits are set).
if (i !== totalPermutations - 1) {
assert.strictEqual(badgedElems.length, 0);
assert.strictEqual(badgedScoreGauge, null);

// Tooltip ends with passing/total.
const passingCount = categoryElem.querySelectorAll(
`.lh-audit-group--${targetGroupId} .lh-audit--pass`).length;
assert.ok(targetGroupTip.endsWith(`${passingCount}/${targetAuditRefs.length}`));
} else {
assert.strictEqual(badgedElems.length, 1);
assert.ok(badgedScoreGauge.classList.contains(`lh-badged--${targetGroupId}`));

// Tooltip ends with total/total.
assert.ok(targetGroupTip.endsWith(`${targetAuditRefs.length}/${targetAuditRefs.length}`));
}
}
});
Expand All @@ -152,7 +165,17 @@ describe('PwaCategoryRenderer', () => {

const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
assert.strictEqual(categoryElem.querySelectorAll('.lh-badged').length, groupIds.length);
assert.ok(categoryElem.querySelector('.lh-gauge--pwa__wrapper.lh-badged--all'));

// Score gauge.
const gaugeElem = categoryElem.querySelector('.lh-gauge--pwa__wrapper');
assert.ok(gaugeElem.classList.contains('lh-badged--all'));

// All tooltips should have x/x audits passed.
const tips = gaugeElem.title.split(', ');
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we assert any length here?

Copy link
Member Author

Choose a reason for hiding this comment

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

should we assert any length here?

good idea, done

assert.strictEqual(tips.length, groupIds.length);
for (const tip of tips) {
assert.ok(/(\d+)\/\1$/.test(tip));
}
});

it('renders no badges when no audit groups are passing', () => {
Expand All @@ -162,8 +185,17 @@ describe('PwaCategoryRenderer', () => {

const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
assert.strictEqual(categoryElem.querySelectorAll('.lh-badged').length, 0);
assert.strictEqual(categoryElem.querySelector('.lh-gauge--pwa__wrapper[class*="lh-badged-"]'),
null);

// Score gauge.
const gaugeElem = categoryElem.querySelector('.lh-gauge--pwa__wrapper');
assert.ok(!gaugeElem.matches('.lh-gauge--pwa__wrapper[class*="lh-badged-"]'));

// All tooltips should have 0/x audits passed.
const tips = gaugeElem.title.split(', ');
assert.strictEqual(tips.length, groupIds.length);
for (const tip of tips) {
assert.ok(/0\/\d+$/.test(tip));
}
});

it('renders all but one badge when all groups but one are passing', () => {
Expand All @@ -176,13 +208,33 @@ describe('PwaCategoryRenderer', () => {
const categoryElem = pwaRenderer.render(category, sampleResults.categoryGroups);
const gaugeElem = categoryElem.querySelector('.lh-gauge--pwa__wrapper');

const tips = gaugeElem.title.split(', ');
assert.strictEqual(tips.length, groupIds.length);

for (const groupId of groupIds) {
const expectedCount = groupId === failingGroupId ? 0 : 1;

// Individual group badges.
const groupElems = categoryElem.querySelectorAll(`.lh-audit-group--${groupId}.lh-badged`);
assert.strictEqual(groupElems.length, expectedCount);

gaugeElem.classList.contains(`lh-badged--${groupId}`);
// Score gauge.
if (groupId !== failingGroupId) {
assert.ok(gaugeElem.classList.contains(`lh-badged--${groupId}`));
}

// Map back from groupId to groupTitle (used in tooltip).
const groupTitle = sampleResults.categoryGroups[groupId].title;
const groupTip = tips.find(tip => tip.startsWith(groupTitle));
assert.ok(groupTip);

// All tooltips should be x/x except for failingGroup, which should be (x-1)/x.
if (groupId !== failingGroupId) {
assert.ok(/(\d+)\/\1$/.test(groupTip));
} else {
const [, passingCount, totalCount] = /(\d+)\/(\d+)$/.exec(groupTip);
assert.strictEqual(Number(passingCount) + 1, Number(totalCount));
}
}
});
});
Expand Down