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

core(lhr): support null scores #5128

Merged
merged 11 commits into from
May 7, 2018
Merged

core(lhr): support null scores #5128

merged 11 commits into from
May 7, 2018

Conversation

patrickhulce
Copy link
Collaborator

@patrickhulce patrickhulce commented May 5, 2018

followup to #5105, add support for null scores and forces all errors/informative/manual/not-applicable to be null

when category errors, the gauge shows '?' I'll try to find a screenshot :)

image

Copy link
Member

@paulirish paulirish left a comment

Choose a reason for hiding this comment

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

love this one. some small ideas but on the whole it's feelin great

return false;
case 'numeric':
case 'binary':
return audit.score === 1;
Copy link
Member

Choose a reason for hiding this comment

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

did you want to handle the case of numeric audits pass if above PASS_THRESHOLD?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah good call 👍

case 'not-applicable':
return true;
case 'error':
case 'informative':
Copy link
Member

Choose a reason for hiding this comment

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

why do all informative audits fail?

Copy link
Collaborator Author

@patrickhulce patrickhulce May 6, 2018

Choose a reason for hiding this comment

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

so they show up as failing, it actually fits perfectly with our new scoreDisplayMode categories. if an informative audit has nothing to tell you it marks itself as not-applicable ;)

Copy link
Member

Choose a reason for hiding this comment

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

aiight sg.

Copy link
Member

Choose a reason for hiding this comment

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

should record this idea somewhere (to the lhr/lhr-lite description of these, maybe?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's more an audit author concern since it's an immediate conclusion from the scoreDisplayMode that if an audit isn't not-applicable it means it was applicable :)

maybe in the custom audit docs?

const perfCategory = sampleResults.reportCategories.find(cat => cat.id === 'performance');
const categoryDOM2 = renderer.render(perfCategory, sampleResults.reportGroups);
assert.ok(!categoryDOM2.querySelector('.lh-audit-group--notapplicable'));
const bestPracticeCat = sampleResults.reportCategories.find(cat => cat.id === 'best-practices');
Copy link
Member

Choose a reason for hiding this comment

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

just curious, why switching to BP? ah because usertimings is now n/a.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah bingo

@@ -275,12 +274,12 @@ class CategoryRenderer {
group = auditsUngrouped;
}

if (audit.result.scoreDisplayMode === 'not-applicable') {
group.notApplicable.push(audit);
} else if (audit.result.score === 1 && !audit.result.debugString) {
Copy link
Member

Choose a reason for hiding this comment

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

that logic on debugString seems rather incorrect tbh. glad it's gone.

@@ -17,7 +17,8 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
const element = this.dom.find('.lh-metric', tmpl);
element.id = audit.result.name;
// FIXME(paulirish): currently this sets a 'lh-metric--fail' class on error'd audits
Copy link
Member

@paulirish paulirish May 5, 2018

Choose a reason for hiding this comment

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

can you also address this?

i'd prefer do not set a --fail class on these audits.

(I know i wrote it and put my own name. haha. So i'm asking super nicely with a cherry on top. :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

haha sure

this.dom.find('.lh-gauge__percentage', tmpl).textContent = scoreOutOf100;
const scoreOutOf100 = Math.round(numericScore * 100);
this.dom.find('.lh-gauge__percentage', tmpl).textContent = category.score === null ?
'?' : scoreOutOf100;
Copy link
Member

Choose a reason for hiding this comment

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

can you also apply a title attribute to that explains why its ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done, text suggestion welcome right now "Errors occurred while auditing"

*/
static arithmeticMean(items) {
// If there is 1 null score, return a null average
if (items.some(item => item.score === null && item.weight !== 0)) return null;
Copy link
Member

Choose a reason for hiding this comment

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

wdyt about an early filter in this method to get rid of the weight===0 items. then we don't need the check in here PLUS L32.
ndb, tho

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah sure sg 👍

@@ -73,7 +73,7 @@ class ReportGenerator {
return category.audits.map(catAudit => {
const audit = lhr.audits[catAudit.id];
return [category.name, audit.name, audit.description, audit.scoreDisplayMode, audit.score]
.map(value => value.toString())
.map(value => value === null ? '0' : value.toString())
Copy link
Member

Choose a reason for hiding this comment

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

i dont know what the CSV consumers want but i feel like getting 0 is a little weird. empty string seems slightly better.

Copy link
Collaborator Author

@patrickhulce patrickhulce May 6, 2018

Choose a reason for hiding this comment

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

csv-validator requires that all values in the column are numbers (I tried 'null' as string originally), I have no preference here we can ditch csv-validator if we want to deviate?

cc @nourikhalass in case you have a preference for how null scores show up in CSV

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with @paulirish that 0 is a bit weird so empty string would be better. But as @patrickhulce says: csv-validator does not play along with that. Maybe its better to use -1 or omit the result entirely if the score is null.

Copy link
Collaborator Author

@patrickhulce patrickhulce May 6, 2018

Choose a reason for hiding this comment

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

I'll go with -1 for now since you're our primary CSV consumer 👍, PR welcome in the future if you think of a better canonical CSV-way to represent this :)

obvious other alternative is just stop validating the scores are numeric, how do you feel about that?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's fine since the validation library leaves a lot to be desired. Maybe in the future I'll look at a better / more robust way of validating the CSV . So I think you'll be OK if you don't validate that scores are numeric.

Also thanks for including me in the loop!

@paulirish
Copy link
Member

@brendankenny you wanna take a look?

@brendankenny
Copy link
Member

looks like manual expectations need updating

@@ -162,18 +163,26 @@ class Audit {

// If the audit was determined to not apply to the page, we'll reset it as informative only
Copy link
Member

Choose a reason for hiding this comment

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

this comment seems out of date now

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

scoreDisplayMode = Audit.SCORING_MODES.NOT_APPLICABLE;
result.rawValue = true;
}

if (result.error) {
Copy link
Member

Choose a reason for hiding this comment

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

is it possible to rework this code to be a flow through a set of mutually exclusive states so it's easy to see the possibilities?

e.g. score is null, if error, it's always scoring mode error, else if it's been marked notApplicable, it's mode notApplicable, then manual, and then only if it's binary or numeric is a score calculated?

description seems like it might not fit the mold, but then maybe it's worth calling separately if it sits across the display modes differently than score does

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this gets reworked immediately as part of #5132, fair to take up there?

Copy link
Member

Choose a reason for hiding this comment

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

fair to take up there?

yeah, SG

@@ -228,14 +225,21 @@ class CategoryRenderer {
wrapper.href = `#${category.id}`;
wrapper.classList.add(`lh-gauge__wrapper--${Util.calculateRating(category.score)}`);

const numericScore = Number(category.score);
Copy link
Member

Choose a reason for hiding this comment

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

should call out casting null to 0 here in a comment

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@@ -259,11 +263,11 @@ class CategoryRenderer {
notApplicable: !Array<!ReportRenderer.AuditJSON>}>} */ ({});
const auditsUngrouped = {passed: [], failed: [], notApplicable: []};

nonManualAudits.forEach(audit => {
nonManualAudits.forEach(auditRef => {
Copy link
Member

Choose a reason for hiding this comment

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

🎉

case 'not-applicable':
return true;
case 'error':
case 'informative':
Copy link
Member

Choose a reason for hiding this comment

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

should record this idea somewhere (to the lhr/lhr-lite description of these, maybe?)

* @param {{score: (number|null), scoreDisplayMode: string}} audit
* @return {boolean}
*/
static didAuditPass(audit) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe this shouldn't be considered if the audit "passed" (we even call out informative audits as not being able to be interpreted as pass/fail lol), but I can't think of a better word and this is the way we divide the sections in the report. Maybe add a comment that this is specifically for that distinction?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah sure sg, I went back and forth on name, basically "shouldHideAudit" but not always

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

actually, I could flip and do "shouldConsiderFailing" or something?

member.weight = 0;
}

Copy link
Member

Choose a reason for hiding this comment

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

I think these members are auditRefs now if you want to do a drive by in this function :)

@patrickhulce
Copy link
Collaborator Author

looks like manual expectations need updating

whoops yeah fixed them on the wrong branch 😆

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

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

LGTM!

@patrickhulce patrickhulce merged commit be71709 into master May 7, 2018
@brendankenny brendankenny deleted the null_scores branch May 7, 2018 19:28
kdzwinel pushed a commit to kdzwinel/lighthouse that referenced this pull request Aug 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants