Skip to content

Checking States Examples

This page demonstrates various patterns for checking element states.

Single State Checks

Example 1: Check Visibility

typescript
async function checkVisibility(element: Element) {
  const result = await inspector.queryElementState(element, 'visible');
  
  console.log('Matches expected state:', result.matches);
  console.log('Actual state:', result.received); // 'visible' or 'hidden'
  
  return result.matches;
}

Example 2: Check Enabled/Disabled

typescript
async function checkEnabled(element: Element) {
  const result = await inspector.queryElementState(element, 'enabled');
  
  if (result.matches) {
    console.log('Element is enabled');
  } else {
    console.log(`Element is ${result.received}`); // 'disabled'
  }
  
  return result.matches;
}

Example 3: Check Viewport Position

typescript
async function checkViewportPosition(element: Element) {
  const result = await inspector.queryElementState(element, 'inview');
  
  console.log('Matches:', result.matches);
  console.log('State:', result.received);
  // Possible states: 'inview', 'notinview', 'unviewable'
  
  if (result.received === 'unviewable') {
    console.log('Element cannot be scrolled into view (hidden by overflow)');
  } else if (result.received === 'notinview') {
    console.log('Element can be scrolled into view');
  } else {
    console.log('Element is currently in viewport');
  }
}

Multiple State Checks

Example 4: Check Button Ready State

typescript
async function isButtonReady(button: Element) {
  const result = await inspector.queryElementStates(
    button,
    ['visible', 'enabled', 'stable']
  );
  
  if (result.status === 'success') {
    console.log('✓ Button is ready for interaction');
    return true;
  } else if (result.status === 'failure') {
    console.log(`✗ Button is not ready: ${result.missingState}`);
    return false;
  } else {
    console.log(`✗ Error checking button: ${result.message}`);
    return false;
  }
}

Example 5: Check Input Ready for Typing

typescript
async function isInputReady(input: Element) {
  const result = await inspector.queryElementStates(
    input,
    ['visible', 'enabled', 'editable']
  );
  
  switch (result.status) {
    case 'success':
      console.log('✓ Input is ready for typing');
      return true;
      
    case 'failure':
      console.log(`✗ Input is not ready: ${result.missingState}`);
      return false;
      
    case 'error':
      console.log(`✗ Error: ${result.message}`);
      return false;
  }
}

Example 6: Comprehensive Element Check

typescript
async function comprehensiveCheck(element: Element) {
  // Check all possible states
  const states = ['visible', 'enabled', 'stable', 'inview'] as const;
  const result = await inspector.queryElementStates(element, states);
  
  if (result.status === 'success') {
    console.log('✓ All states passed');
    return { ready: true };
  } else if (result.status === 'failure') {
    console.log(`✗ Missing state: ${result.missingState}`);
    return { ready: false, missingState: result.missingState };
  } else {
    console.log(`✗ Error: ${result.message}`);
    return { ready: false, error: result.message };
  }
}

Conditional State Checks

Example 7: Check States Based on Element Type

typescript
async function checkElementReady(element: Element) {
  const tagName = element.tagName.toLowerCase();
  
  let states: ElementState[];
  
  if (['input', 'textarea'].includes(tagName)) {
    // For inputs, check if editable
    states = ['visible', 'enabled', 'editable'];
  } else if (['button', 'a'].includes(tagName)) {
    // For buttons and links, just check if clickable
    states = ['visible', 'enabled'];
  } else {
    // For other elements, just check visibility
    states = ['visible'];
  }
  
  const result = await inspector.queryElementStates(element, states);
  
  return {
    ready: result.status === 'success',
    states,
    result
  };
}

Example 8: Progressive State Checking

typescript
async function progressiveCheck(element: Element) {
  // Check states one by one for detailed feedback
  
  console.log('Checking visibility...');
  const visibleResult = await inspector.queryElementState(element, 'visible');
  if (!visibleResult.matches) {
    return { ready: false, failedAt: 'visible' };
  }
  
  console.log('✓ Visible - Checking enabled...');
  const enabledResult = await inspector.queryElementState(element, 'enabled');
  if (!enabledResult.matches) {
    return { ready: false, failedAt: 'enabled' };
  }
  
  console.log('✓ Enabled - Checking viewport...');
  const inviewResult = await inspector.queryElementState(element, 'inview');
  if (!inviewResult.matches) {
    return { ready: false, failedAt: 'inview', state: inviewResult.received };
  }
  
  console.log('✓ In viewport - Checking stability...');
  const stableResult = await inspector.queryElementStates(element, ['stable']);
  if (stableResult.status !== 'success') {
    return { ready: false, failedAt: 'stable' };
  }
  
  console.log('✓ All checks passed');
  return { ready: true };
}

State Monitoring

Example 9: Monitor State Changes

typescript
async function monitorElementState(
  element: Element,
  duration: number = 5000
) {
  const start = Date.now();
  const history: Array<{ time: number; visible: boolean; enabled: boolean }> = [];
  
  while (Date.now() - start < duration) {
    const visible = inspector.isElementVisible(element);
    const enabled = !inspector.isElementDisabled(element);
    
    history.push({
      time: Date.now() - start,
      visible,
      enabled
    });
    
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  console.log('State history:', history);
  
  // Analyze stability
  const changes = history.filter((state, i) => {
    if (i === 0) return false;
    const prev = history[i - 1];
    return state.visible !== prev.visible || state.enabled !== prev.enabled;
  });
  
  console.log(`State changed ${changes.length} times in ${duration}ms`);
  
  return { history, changes };
}

Example 10: Wait for State Change

typescript
async function waitForStateChange(
  element: Element,
  expectedState: 'visible' | 'hidden',
  timeout: number = 5000
) {
  const start = Date.now();
  
  while (Date.now() - start < timeout) {
    const result = await inspector.queryElementState(element, expectedState);
    
    if (result.matches) {
      const elapsed = Date.now() - start;
      console.log(`✓ Element became ${expectedState} after ${elapsed}ms`);
      return true;
    }
    
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  console.log(`✗ Element did not become ${expectedState} within ${timeout}ms`);
  return false;
}

// Usage
await waitForStateChange(element, 'visible', 3000);

Batch State Checks

Example 11: Check Multiple Elements' States

typescript
async function batchStateCheck(
  elements: Element[],
  requiredStates: ElementState[]
) {
  const results = await Promise.all(
    elements.map(async (element, index) => {
      const result = await inspector.queryElementStates(element, requiredStates);
      
      return {
        index,
        element,
        ready: result.status === 'success',
        missingState: result.status === 'failure' ? result.missingState : null,
        error: result.status === 'error' ? result.message : null
      };
    })
  );
  
  const readyCount = results.filter(r => r.ready).length;
  console.log(`${readyCount}/${elements.length} elements are ready`);
  
  return results;
}

// Usage
const buttons = Array.from(document.querySelectorAll('.action-button'));
const results = await batchStateCheck(buttons, ['visible', 'enabled']);

Example 12: Find First Ready Element

typescript
async function findFirstReady(
  selectors: string[],
  requiredStates: ElementState[]
): Promise<Element | null> {
  for (const selector of selectors) {
    const element = document.querySelector(selector);
    if (!element) continue;
    
    const result = await inspector.queryElementStates(element, requiredStates);
    
    if (result.status === 'success') {
      console.log(`✓ Found ready element: ${selector}`);
      return element;
    }
  }
  
  console.log('✗ No ready elements found');
  return null;
}

// Usage
const button = await findFirstReady(
  ['#primary-button', '#secondary-button', '#fallback-button'],
  ['visible', 'enabled']
);

Error Handling

Example 13: Robust State Checking

typescript
async function robustStateCheck(element: Element) {
  try {
    const result = await inspector.queryElementStates(
      element,
      ['visible', 'enabled', 'stable']
    );
    
    if (result.status === 'success') {
      return { success: true };
    } else if (result.status === 'failure') {
      return {
        success: false,
        reason: 'missing_state',
        missingState: result.missingState
      };
    } else {
      return {
        success: false,
        reason: 'error',
        message: result.message
      };
    }
  } catch (error) {
    console.error('Unexpected error during state check:', error);
    return {
      success: false,
      reason: 'exception',
      error
    };
  }
}

Example 14: Validate Editable State Safely

typescript
async function safeEditableCheck(element: Element) {
  const tagName = element.tagName.toLowerCase();
  const isContentEditable = element.hasAttribute('contenteditable');
  
  // Only check editable for appropriate elements
  if (!['input', 'textarea', 'select'].includes(tagName) && !isContentEditable) {
    return {
      editable: false,
      reason: 'Element type does not support editable state'
    };
  }
  
  try {
    const result = await inspector.queryElementState(element, 'editable');
    return {
      editable: result.matches,
      state: result.received
    };
  } catch (error) {
    return {
      editable: false,
      reason: 'Error checking editable state',
      error
    };
  }
}

Next Steps

Released under the Apache License 2.0.