class_docstr: Test default waiters.
class_docstr_tok: ["Test","default","waiters","."]
docstr: Test `JobComplete` waiter reach `FAILED` status.
docstr_tok: ["Test","`","JobComplete","`","waiter","reach","`","FAILED","`","status","."]
code: def test_job_complete_waiter_failed(self):
      """Test `JobComplete` waiter reach `FAILED` status."""
      job_id = "job-failed"
      self.mock_describe_jobs.side_effect = [
          *itertools.repeat(
              self.describe_jobs_response(
                  job_id=job_id, status=RUNNING_STATE
              ),
              10,
          ),
          self.describe_jobs_response(
              job_id=job_id, status=FAILED_STATE
          ),
          RuntimeError("This should not raise"),
      ]
  
      job_complete_waiter = self.batch_waiters.get_waiter("JobComplete")
      job_complete_waiter.config.delay = 0.01
      job_complete_waiter.config.max_attempts = 20
      with pytest.raises(
          WaiterError,
          match="Waiter JobComplete failed: Waiter encountered a terminal failure state",
      ):
          job_complete_waiter.wait(jobs=[job_id])
      assert self.mock_describe_jobs.called
  
imports: from __future__ import annotations
  import inspect
  import itertools
  import time
  from unittest import mock
  import boto3
  import pytest
  from botocore.exceptions import ClientError, WaiterError
  from botocore.waiter import SingleWaiterConfig, WaiterModel
  from moto import mock_batch
  from airflow.exceptions import AirflowException
  from airflow.providers.amazon.aws.hooks.batch_waiters import BatchWaitersHook
  from airflow.providers.amazon.aws.utils.task_log_fetcher import AwsTaskLogFetcher
label_desc: Use image node_id 8 for calling the TestBatchJobWaiters obj's underlying member method code with example usage: obj.test_job_complete_waiter_failed() without return types