static audit(artifacts) {
    const failingFormsData = [];
    const warnings = [];
    let foundPrediction = false;
    for (const input of artifacts.Inputs.inputs) {
      const validity = this.checkAttributeValidity(input);
      if (validity.hasValidTokens && validity.isValidOrder) continue;
      if (!input.autocomplete.prediction) continue;
      if (noPrediction.includes(input.autocomplete.prediction) &&
        !input.autocomplete.attribute) continue;

      foundPrediction = true;

      // @ts-ignore
      let suggestion = predictionTypesToTokens[input.autocomplete.prediction];
      // This is here to satisfy typescript because the possible null value of autocomplete.attribute is not compatible with Audit details.
      if (!input.autocomplete.attribute) input.autocomplete.attribute = '';
      // Warning is created because while there is an autocomplete attribute, the autocomplete property does not exsist, thus the attribute's value is invalid.
      if (input.autocomplete.attribute) {
        warnings.push(str_(UIStrings.warningInvalid, {token: input.autocomplete.attribute,
          snippet: input.node.snippet}));
      }
      if (validity.isValidOrder === false) {
        warnings.push(str_(UIStrings.warningOrder, {tokens: input.autocomplete.attribute,
          snippet: input.node.snippet}));
        suggestion = UIStrings.reviewOrder;
      }
      // If the autofill prediction is not in our autofill suggestion mapping, then we warn
      if (!(input.autocomplete.prediction in predictionTypesToTokens) &&
          validity.isValidOrder) {
        log.warn(`Autocomplete prediction (${input.autocomplete.prediction})
            not found in our mapping`);
        continue;
      }
      failingFormsData.push({
        node: Audit.makeNodeItem(input.node),
        suggestion: suggestion,
        current: input.autocomplete.attribute,
      });
    }

    /** @type {LH.Audit.Details.Table['headings']} */
    const headings = [
      {key: 'node', valueType: 'node', label: str_(i18n.UIStrings.columnFailingElem)},
      {key: 'current', valueType: 'text', label: str_(UIStrings.columnCurrent)},
      {key: 'suggestion', valueType: 'text', label: str_(UIStrings.columnSuggestions)},
    ];
    const details = Audit.makeTableDetails(headings, failingFormsData);
    let displayValue;
    if (failingFormsData.length > 0) {
      displayValue = str_(i18n.UIStrings.displayValueElementsFound,
        {nodeCount: failingFormsData.length});
    }
    return {
      score: (failingFormsData.length > 0) ? 0 : 1,
      notApplicable: !foundPrediction,
      displayValue,
      details,
      warnings,
    };
  }
@param {LH.Artifacts} artifacts
@return {LH.Audit.Product}