 create or replace package body test_realtime_reporter as
 
-  g_actual_xml_report xmltype;
+  g_xml_reports test_xmltype_list := test_xmltype_list();
 
   procedure create_test_suites_and_run is
     pragma autonomous_transaction;

    end;]';
    
    <<run_report_and_cache_result>>
    declare
      l_results ut3.ut_varchar2_list;
    begin
      select *
        bulk collect into l_results
        from table(ut3.ut.run('ut3_tester:realtime_reporting', ut3.ut_realtime_reporter()));
      g_actual_xml_report := xmltype(ut3.ut_utils.table_to_clob(l_results));
    end run_report_and_cache_result;
  end create_test_suites_and_run;
  
  procedure xml_report_structure is
    l_actual        clob;
    l_expected_list ut3.ut_varchar2_list;
    l_expected      clob;
  begin
    l_actual := g_actual_xml_report.getclobval();
    ut3.ut_utils.append_to_list(l_expected_list, '<?xml version="1.0"?>');
    ut3.ut_utils.append_to_list(l_expected_list, '%<report>');
    ut3.ut_utils.append_to_list(l_expected_list, '%  <preRun>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    <suites>');
    ut3.ut_utils.append_to_list(l_expected_list, '%      <suite id="%">');
    ut3.ut_utils.append_to_list(l_expected_list, '%        %<test id="%">');
    ut3.ut_utils.append_to_list(l_expected_list, '%        %</test>');
    ut3.ut_utils.append_to_list(l_expected_list, '%      </suite>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    </suites>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    <totalNumberOfTests>%</totalNumberOfTests>');
    ut3.ut_utils.append_to_list(l_expected_list, '%  </preRun>');
    ut3.ut_utils.append_to_list(l_expected_list, '%  <runEvents>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    <startSuiteEvent id="%">');
    ut3.ut_utils.append_to_list(l_expected_list, '%    </startTestEvent>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    <startTestEvent id="%">');
    ut3.ut_utils.append_to_list(l_expected_list, '%    </startTestEvent>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    <endTestEvent id="%">');
    ut3.ut_utils.append_to_list(l_expected_list, '%    </endTestEvent>');
    ut3.ut_utils.append_to_list(l_expected_list, '%    <endSuiteEvent id="%">');
    ut3.ut_utils.append_to_list(l_expected_list, '%    </endSuiteEvent>');
    ut3.ut_utils.append_to_list(l_expected_list, '%  </runEvents>');
    ut3.ut_utils.append_to_list(l_expected_list, '%</report>');
    l_expected := ut3.ut_utils.table_to_clob(l_expected_list, null);
    ut.expect(l_actual).to_be_like(l_expected);
  end xml_report_structure;
  
  procedure total_number_of_tests is
    l_actual   integer;
    l_expected integer := 7; 
  begin
    l_actual := g_actual_xml_report.extract('/report/preRun/totalNumberOfTests/text()').getnumberval();
    ut.expect(l_actual).to_equal(l_expected);
  end total_number_of_tests; 
  
  procedure escaped_characters is
    l_actual   varchar2(32767);
    l_expected varchar2(20) := 'suite &lt;A&gt;'; 
  begin
    l_actual := 
      g_actual_xml_report.extract(
        '//suite[@id="realtime_reporting.check_realtime_reporting1"]/description/text()'
      ).getstringval();
    ut.expect(l_actual).to_equal(l_expected);
  end escaped_characters;
  
  procedure number_of_starttestevent_nodes is
    l_actual   integer;
    l_expected integer := 7;
  begin
    select count(*)
      into l_actual
      from xmltable(
             '/report/runEvents/startTestEvent'
             passing g_actual_xml_report
             columns id                    varchar2(4000) path '@id',
                     test_number           integer        path 'testNumber',
                     total_number_of_tests integer        path 'totalNumberOfTests'
           )
     where id is not null
       and test_number is not null
       and total_number_of_tests is not null;
    ut.expect(l_actual).to_equal(l_expected);
  end number_of_starttestevent_nodes;
  
  procedure endtestevent_nodes is
    l_actual   sys_refcursor;
    l_expected sys_refcursor;
  begin
    open l_actual for
      select test_number, total_number_of_tests
        from xmltable(
               '/report/runEvents/endTestEvent'
               passing g_actual_xml_report
               columns id                    varchar2(4000) path '@id',
                       test_number           integer        path 'testNumber',
                       total_number_of_tests integer        path 'totalNumberOfTests'
             )
       where id is not null
         and test_number is not null
         and total_number_of_tests is not null;
    open l_expected for
       select level as test_number, 
              7     as total_number_of_tests 
         from dual
      connect by level <= 7;
    ut.expect(l_actual).to_equal(l_expected).unordered;
  end endtestevent_nodes;

  procedure single_failed_message is
    l_actual   varchar2(32767);
    l_expected varchar2(80) := '<![CDATA[Actual: 1 (number) was expected to equal: 2 (number) ]]>';
  begin
    l_actual := 
      g_actual_xml_report.extract(
        '/report/runEvents/endTestEvent[@id="realtime_reporting.check_realtime_reporting1.test context.test_2_nok"]/failedExpectations/expectation[1]/message/text()'
      ).getstringval();
    ut.expect(l_actual).to_equal(l_expected);
  end single_failed_message;
  

    l_expected_list ut3.ut_varchar2_list;
    l_expected clob;
  begin
    select t.column_value.extract('//event/suite/serverOutput/text()').getstringval()
      into l_actual
      from table(g_xml_reports) t
     where t.column_value.extract('/event[@type="post-suite"]/suite/@id').getstringval() 
           = 'realtime_reporting.check_realtime_reporting3';
    ut3.ut_utils.append_to_list(l_expected_list, '<![CDATA[Now, a no_data_found exception is raised');
    ut3.ut_utils.append_to_list(l_expected_list, 'dbms_output and error stack is reported for this suite.');
    ut3.ut_utils.append_to_list(l_expected_list, 'A runtime error in afterall is counted as a warning.');
