All files / packages/sds-customization-compliance/src/checks/helpers ignoredSelectors.ts

66.66% Statements 16/24
58.82% Branches 10/17
80% Functions 4/5
66.66% Lines 12/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62                                        1x               9x 9x 1x                                       9x 9x 1x 1x 1x 1x 1x     1x    
/**
 * Drop flags whose selector is listed in {@link IGNORED_SELECTORS} for
 * the component under test.
 *
 * Used by the two regression-based compliance checks to silently ignore
 * cleanup of cross-component baggage (e.g. the legacy icon CSS styling
 * `.slds-input__icon`, which structurally belongs to the input
 * component). See `config/ignoredSelectors.ts` for the maintained list
 * and the reasoning behind each entry.
 *
 * Matching is done on the flag's primary selector — either `flag.selector`
 * or the selector carried on the legacy/next side — compared via the
 * normalized `selectorKey` so whitespace / comma-ordering differences
 * between the entry and the source CSS don't break the match.
 */
import { selectorKey } from '../../audit/extract.js';
import { IGNORED_SELECTORS } from '../../config/ignoredSelectors.js';
import type { Flag } from '../../audit/types.js';
 
function flagSelector(flag: Flag): string | undefined {
  return flag.selector ?? flag.legacy?.selector ?? flag.next?.selector;
}
 
/**
 * Returns the ignore list for a component with each entry pre-normalized,
 * so repeated lookups during a check run don't re-normalize on every flag.
 */
function normalizedIgnoreList(componentName: string): Set<string> | null {
  const list = IGNORED_SELECTORS[componentName];
  if (!list || list.length === 0) return null;
  return new Set(list.map((s) => selectorKey(s)));
}
 
export function isIgnoredFlag(componentName: string, flag: Flag): boolean {
  const ignored = normalizedIgnoreList(componentName);
  if (!ignored) return false;
  const selector = flagSelector(flag);
  if (!selector) return false;
  return ignored.has(selectorKey(selector));
}
 
/**
 * Split `flags` into `{kept, ignored}`. Callers score against `kept` and
 * may choose to count `ignored.length` for diagnostics, but the row's
 * visible offender list is built from `kept` only.
 */
export function partitionIgnoredFlags(
  componentName: string,
  flags: readonly Flag[],
): { kept: Flag[]; ignored: Flag[] } {
  const ignored = normalizedIgnoreList(componentName);
  if (!ignored) return { kept: [...flags], ignored: [] };
  const keptList: Flag[] = [];
  const ignoredList: Flag[] = [];
  for (const f of flags) {
    const sel = flagSelector(f);
    if (sel && ignored.has(selectorKey(sel))) ignoredList.push(f);
    else EkeptList.push(f);
  }
  return { kept: keptList, ignored: ignoredList };
}