All files conditions.ts

100% Statements 32/32
95.45% Branches 21/22
100% Functions 8/8
100% Lines 27/27

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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                    1x       10x     9x 2x 1x         8x 2x           1x         7x 2x           1x         6x 1x           1x         5x 2x 1x       4x               1x       5x 4x       1x       6x       1x       6x       1x       5x    
/**
 * WalkMe Conditions Module
 *
 * Conditional display evaluation for tours.
 * All specified conditions must pass (AND logic).
 */
 
import type { TourConditions, ConditionContext } from '../types/walkme.types'
 
// ---------------------------------------------------------------------------
// Main Evaluation
// ---------------------------------------------------------------------------
 
/**
 * Evaluate all conditions for a tour.
 * Returns true if no conditions are specified or all conditions pass.
 * Uses AND logic: every specified condition must be satisfied.
 */
export function evaluateConditions(
  conditions: TourConditions | undefined,
  context: ConditionContext,
): boolean {
  if (!conditions) return true
 
  // Check user role
  if (conditions.userRole && conditions.userRole.length > 0) {
    if (!evaluateRoleCondition(conditions.userRole, context.userRole)) {
      return false
    }
  }
 
  // Check feature flags
  if (conditions.featureFlags && conditions.featureFlags.length > 0) {
    if (
      !evaluateFeatureFlagCondition(
        conditions.featureFlags,
        context.featureFlags ?? [],
      )
    ) {
      return false
    }
  }
 
  // Check completed tours
  if (conditions.completedTours && conditions.completedTours.length > 0) {
    if (
      !evaluateCompletedToursCondition(
        conditions.completedTours,
        context.completedTourIds,
      )
    ) {
      return false
    }
  }
 
  // Check not-completed tours
  if (conditions.notCompletedTours && conditions.notCompletedTours.length > 0) {
    if (
      !evaluateNotCompletedCondition(
        conditions.notCompletedTours,
        context.completedTourIds,
      )
    ) {
      return false
    }
  }
 
  // Check custom condition
  if (conditions.custom) {
    if (!conditions.custom(context)) {
      return false
    }
  }
 
  return true
}
 
// ---------------------------------------------------------------------------
// Individual Condition Evaluators
// ---------------------------------------------------------------------------
 
/** User role must be in the allowed list */
export function evaluateRoleCondition(
  roles: string[],
  userRole: string | undefined,
): boolean {
  if (!userRole) return false
  return roles.includes(userRole)
}
 
/** All specified feature flags must be active */
export function evaluateFeatureFlagCondition(
  requiredFlags: string[],
  activeFlags: string[],
): boolean {
  return requiredFlags.every((flag) => activeFlags.includes(flag))
}
 
/** All specified tours must be completed */
export function evaluateCompletedToursCondition(
  requiredTours: string[],
  completedTourIds: string[],
): boolean {
  return requiredTours.every((tourId) => completedTourIds.includes(tourId))
}
 
/** None of the specified tours should be completed */
export function evaluateNotCompletedCondition(
  excludedTours: string[],
  completedTourIds: string[],
): boolean {
  return !excludedTours.some((tourId) => completedTourIds.includes(tourId))
}