import { KEYWORD_TESTS, type Analysis, type AnalysisResult, } from '../analysis/analyzer'; import { isToDo, isToFix } from '../components/result-tone'; /** What an analysis leaves to do, as the panel lists it and Fix with AI is told. */ export interface FailingTests { /** The tests that count: without a focus keyword, the keyword tests are left out. */ counted: AnalysisResult[]; /** Of those, the ones that weigh on the score. */ weighted: AnalysisResult[]; /** How many of the weighted ones passed. */ passed: number; /** * The tests that lost all their points first, then the ones that earned * part of them, then the advice (AI answers, keyword used before, a long * post's table of contents). Tests shown for comparison only are never in it. */ failing: AnalysisResult[]; /** The failing tests in the words the panel shows, with the remedy after each. */ failingLines: string[]; /** What goes to Fix with AI, line by line and by id. */ fixLines: string[]; fixIds: string[]; } /** * A test in the words the panel shows, with its remedy after it. * * @param result - One test. * @return "message (fix)". */ export const lineOf = (result: AnalysisResult): string => `${result.message}${result.fix ? ` (${result.fix})` : ''}`; /** * The failing tests of an analysis. Without a focus keyword the keyword * tests have nothing to measure: they are neither listed as failing nor * sent to be fixed. The agent answers the tests sent to it one by one; it * reads the media test as a page without a picture and has the merchant * upload one, so a page that has some, and only earned part of the * points, is not sent that test. * * @param analysis - The analysis of one page and keyword. * @return What it leaves to do. */ export const failingTests = (analysis: Analysis): FailingTests => { const counted = analysis.needsKeyword ? analysis.results.filter(result => !KEYWORD_TESTS.includes(result.id)) : analysis.results; const weighted = counted.filter(result => result.max > 0); const failing = [ ...weighted.filter(isToFix), ...weighted.filter(result => result.partial && isToDo(result)), ...counted.filter(result => result.max === 0 && isToDo(result)), ]; const fixable = failing.filter( result => !(result.id === 'contentHasAssets' && result.partial) ); return { counted, weighted, passed: weighted.filter(result => result.passed).length, failing, failingLines: failing.map(lineOf), fixLines: fixable.map(lineOf), fixIds: fixable.map(result => result.id), }; };