Sunday 16 December 2018

with Attachement

/*
    Name               : AutomatedTestSetup_Controller
    Test class         : AutomatedTestSetup_Controller_Test
    Description        : For Automated Test class execution process(SP-684-Automate Test Classes execution in Salesforce Orgs)
    Created By         : Krishna yerru
    Created Date       : 23-Oct-2018

********************************************************************************************************************************
    Change Version   Name              Date                    Task/Case#                 Description
********************************************************************************************************************************
 CH0001          Krishna Yerru       08-Nov-2018             SP-2793                 Enhance Automated Test Execution to allow continuous runs
********************************************************************************************************************************   
*/


public with sharing class AutomatedTestSetup_Controller {

    public boolean hasScheduledJobs { get; set; }
    public boolean hasAbort { get; set; }
    public boolean hasemailpending { get; set; }
    public boolean isRunning { get; set; }
    public boolean isEmailing { get; set; }
    public AutomatedTestSetup_Controller ATS { get; set; }
    public String DtValue {get; set; }
    public boolean showMessage {get;set;}
    public String showdatetime{get;set;}
    public String Staticstics{get;set;}
    public Decimal Percentage{get;set;}
    public String shddatetime {get;set;}
    public String ATRdetails {get;set;}
    public String PastATRdetails {get;set;}
    public List<CronTrigger> SchdjobsAdhoc{get;set;} //CH0001
    public List<CronTrigger> Schdjobs{get;set;}
    public String Jobstatus  {get;set;}
    public Automated_Test_Run__c AtrRecord  {get; set;}
    public Boolean isChecked { get; set; }//CH0001
    public Boolean isCheckedRec { get; set; }//CH0001
    public Boolean isAdhocChecked { get; set; }//CH0001
    public Boolean reccurenceMsg;//CH0001
    public Boolean AdhocMsg;//CH0001
    //recurrence related-CH0001
    public boolean hasRecScheduledJobs { get; set; }   
     id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
     id ATEmailRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
     //MultipleAdhocJobs
    public string SelectedAdhocJobId { get; set; }//CH0001

    public PageReference doInsert() {
        AdhocMsg=false;//CH0001
       List<Automated_Test_Run__c> ATSrecrdsinsert=New List<Automated_Test_Run__c>();
        String ADrandomnumberis=generateRandomNumber();//CH0001
        String ADScheduleNameis='AutoTestRunnerAdhoc_'+AtrRecord.Query__c +'_'+ADrandomnumberis;
        AtrRecord.Query__c=AtrRecord.Query__c;
        AtrRecord.Excluded_Classes__c=AtrRecord.Excluded_Classes__c;
        AtrRecord.Exclude_Managed_Packages__c=AtrRecord.Exclude_Managed_Packages__c;
        AtrRecord.Schedule__c=AtrRecord.Schedule__c;
        AtrRecord.Schedule_Name__c= ADScheduleNameis;//CH0001
     
        AtrRecord.RecordTypeId=ATERecordTypeId;
        ATSrecrdsinsert.add(AtrRecord);
     
        Automated_Test_Run__c ATEemail = new Automated_Test_Run__c();
        ATEemail.Query__c=AtrRecord.Query__c;
        ATEemail.Emails__c=AtrRecord.Emails__c;
        ATEemail.Email_on_Pass__c=AtrRecord.Email_on_Pass__c;
        ATEemail.Schedule__c=AtrRecord.Schedule__c;//CH0001
        ATEemail.Schedule_Name__c= ADScheduleNameis;//CH0001
        ATEemail.RecordTypeId=ATEmailRecordTypeId;
        ATSrecrdsinsert.add(ATEemail);
        Savepoint sp = Database.setSavepoint();
        //CH0001-Modified-Start
        try{
            System.debug('AtrRecord.Schedule__c is***'+AtrRecord.Schedule__c);
            System.debug('AtrRecord.Schedule__c is***'+datetime.now());
            if(AtrRecord.Schedule__c>=datetime.now()){
                    scheduleJobs(AtrRecord.Schedule__c,ADScheduleNameis);
                    if(showMessage==false){
                        upsert ATSrecrdsinsert;             
                    } 
                }   else{
                    AdhocMsg=true;
                    ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,'Schedule Date Time Must be Greater than current time');
                    ApexPages.addMessage(myMsg);
                }         
        }
        catch(exception ex){
            Database.rollback(sp);         
        }
       
        PageReference pageRef;
        if(AdhocMsg==true){
            pageRef=null;
        }else if(AdhocMsg==false){
            GetATSRunDeatils();
            pageRef = new PageReference('/apex/AutomatedTestSetup');
            pageRef.setRedirect(true);
        }
      return pageRef;
     
            //return null;
        //CH0001-Modifed End
    }
    public Automated_Test_Run__c getAtrRecord()
    {
        return AtrRecord;
    }
 
  //CH0001-Modified  start
    public AutomatedTestSetup_Controller(ApexPages.StandardController controller) {     
        AtrRecord = (Automated_Test_Run__c)Controller.getRecord();
        this.ATS=ATS;     
        showMessage=false;
        ScheduledJobs();
        refreshHasScheduledJobs();   
        ShowAbortbutton();
        getPieData();
        Calculatepercentage();
        GetATSRunDeatils();
        EmailSendPending();
        //recurrence related
        System.debug('isCheckedRec value is1 '+isCheckedRec);
        //isCheckedRec=false;
        System.debug('isCheckedRec value is12is '+isCheckedRec);
            if(isChecked==null){
             isCheckedRec = false;
             System.debug('isCheckedRec is ' +isCheckedRec);
         }
        if(isAdhocChecked==null){
             isAdhocChecked = false;
             System.debug('isAdhocChecked is ' +isAdhocChecked);
         } 
           
        refreshHasRecrnsScheduledJobs();
    }   

    public void refreshHasScheduledJobs() {   
        integer jobCount = [SELECT count() FROM CronTrigger  where CronJobDetail.Name like '%AutoTestRunnerAdhoc%'];
        SchdjobsAdhoc=[SELECT CronJobDetail.Name,CreatedDate,TimesTriggered,NextFireTime,State FROM CronTrigger where CronJobDetail.Name like '%AutoTestRunnerAdhoc%' and State in('WAITING','ACQUIRED','EXECUTING')];
        if(SchdjobsAdhoc.size()>0){
        //if(SchdjobsAdhoc!=null){
            Jobstatus=SchdjobsAdhoc[0].State;
            if(SchdjobsAdhoc[0].NextFireTime!=null ){
            Datetime shddatetimeGSt=SchdjobsAdhoc[0].NextFireTime;
            Datetime gmt = shddatetimeGSt;
             String timeZone = UserInfo.getTimeZone().getID();
             Datetime GivenDateTime=shddatetimeGSt;// here you can user your dates e.g. createddate
              Datetime localdt=Datetime.valueOf(GivenDateTime);
              //showdatetime = string.valueOfGmt(local);
              shddatetime=localdt.format();
              }
              else if(Jobstatus!=null && Jobstatus!='') {
                  shddatetime='Test Scheduled Job Current State is '+Jobstatus;
              }
            }         
        hasScheduledJobs = jobCount !=0;       
    }
    //CH0001-Modified  End
    public void GetATSRunDeatils() {
        List<String> Keywords=New List<String>();
        Keywords.clear();
        ATRdetails='';
        for(Automated_Test_Run__c atr: [select Query__c, Excluded_Classes__c,
                            Email_on_Pass__c, Exclude_Managed_Packages__c
                            from Automated_Test_Run__c
                            //where Active__c = true and RecordTypeId=:ATERecordTypeId order by createdDate DESC limit 1]){
                            where RecordTypeId=:ATERecordTypeId order by createdDate DESC limit 1]){
                        Keywords.add(atr.Query__c);                   
        }
        if(Keywords.size()>0){
            for(String kw:Keywords){
            ATRdetails+=kw;
            }
        }
    }

    public void ShowAbortbutton(){
        integer runCount = [select count() from Automated_Test_Run__c limit 1];
        List<Test_Runner_Job__c> RunningJobnm =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
         List<ID> TRIDS=New List<ID>();//CH001
        //CH0001_Change_Started
        if(RunningJobnm.size()>0){     
                for(Automated_Test_Run__c ATSrec:[select id,Query__c ,(Select Name from Test_Runner_Jobs__r) from Automated_Test_Run__c where id=:RunningJobnm[0].Automated_Test_Run__c]){
                    for(Test_Runner_Job__c TR:ATSrec.Test_Runner_Jobs__r) {
                    TRIDS.add(TR.Name);
                    System.debug(TR.Name);
                    }
                }
                System.debug('ParentJobIDS are'+TRIDS);   
            integer TestexecrunCount = [select count() from ApexTestQueueItem WHERE Status IN ('Holding','Queued','Preparing','Processing') and ParentJobId in:TRIDS];
            hasAbort = TestexecrunCount > 0; 
         }  //CH0001_Change_END 
    }
 
    public void EmailSendPending(){
        List<Test_Runner_Job__c> runCountJob = [select id from Test_Runner_Job__c where Processed__c=false order by CreatedDate desc limit 1];
        hasemailpending = runCountJob.size()> 0;               
    }

    public string getTestRunLink() {
        return '/' + Automated_Test_Run__c.SObjectType.getDescribe().getKeyPrefix();
    }
    //CH0001-New Method
    public PageReference getHomeLink() {
        PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
                    pageRef.setRedirect(true);
                    return pageRef;
    }
   
    public AutomatedTestSetup_Controller() {
         Automated_Test_Run__c AtrRecord = new Automated_Test_Run__c();
         refreshHasScheduledJobs();
         ScheduledJobs();////CH0001-Modified  start
         Calculatepercentage();
         ShowAbortbutton();
         EmailSendPending();
        ////CH0001-Modified  start
        System.debug('isCheckedRec value is1 '+isCheckedRec);
        //isCheckedRec=false;
        System.debug('isCheckedRec value is12is '+isCheckedRec);
        //click();
         if(isChecked==null){
             isCheckedRec = false;
             System.debug('isCheckedRec is ' +isCheckedRec);
         }
         if(isAdhocChecked==null){
             isAdhocChecked = false;
             System.debug('isAdhocChecked is ' +isAdhocChecked);
         }
        //CH0001-Modified  end
    }
 
    public PageReference scheduleJobs(Datetime DtValue,String ADScheduleNameis) {
     
        System.debug('Date & Time is given***1'+DtValue);
        deleteCompletedJobs();
        Datetime gmt = DtValue;
        String timeZone = UserInfo.getTimeZone().getID();
        Datetime GivenDateTime=DtValue;// here you can user your dates e.g. createddate
         System.debug('GivenDateTime is***'+GivenDateTime);       
                Datetime local=Datetime.valueOf(GivenDateTime);
                System.debug('local is***'+local);
                Map <Integer,String> monthNumbers = new Map <Integer,String> {1=>'Jan', 2=>'Feb',3=>'Mar',4=>'Apr', 5=>'May', 6=>'Jun',7=>'Jul',8=>'Aug', 9=>'Sep', 10=>'Oct', 11=>'Nov', 12=>'Dec'};
                String TestShdmonth=monthNumbers.get(local.month());
                String strSchedule = '0 ' + local.minute() + ' ' +local.hour()+ ' ' + local.day()+ ' ' + TestShdmonth+ ' ? ' + ' ' + local.year();
                System.debug('***strSchedule***'+strSchedule);
                AutoTestRunner.setup(strSchedule,ADScheduleNameis);
                refreshHasScheduledJobs();           
                GetATSRunDeatils();
             
             
     
    return null;
    }

    public PageReference AbortTestJobs() { 
        List<Test_Runner_Job__c> RunningJobnm =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
        List<ID> TRIDS=New List<ID>();//CH001
        //CH0001_Change_Started           
                for(Automated_Test_Run__c ATSrec:[select id,Query__c ,(Select Name from Test_Runner_Jobs__r) from Automated_Test_Run__c where id=:RunningJobnm[0].Automated_Test_Run__c]){
                    for(Test_Runner_Job__c TR:ATSrec.Test_Runner_Jobs__r) {
                    TRIDS.add(TR.Name);
                    System.debug(TR.Name);
                    }
                }
                System.debug('ParentJobIDS are'+TRIDS);
       
        ApexTestQueueItem[] items = [SELECT Id FROM ApexTestQueueItem WHERE Status IN ('Holding','Queued','Preparing','Processing') and ParentJobId in:TRIDS];
        //CH0001_Change_End
        if(items.size()>0){
                for(ApexTestQueueItem item: items) {
                    item.Status = 'Aborted';
                }
                update items;
           }
         email();
        PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
        pageRef.setRedirect(true);
        return pageRef;
    }
 
    public void deleteCompletedJobs(){
        List<CronTrigger> jobsToAbort = [select Id,State from CronTrigger where CronJobDetail.JobType = '7' and CronJobDetail.Name like '%TestRunner%' and State='DELETED'];
              for (CronTrigger job : jobsToAbort) {
               System.abortJob(job.Id);
               }   
    }

    public void email() {
        emailUnprocessedJobStatus();
        isEmailing = true;
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.Confirm, 'Results processed and emailed'));
    }
 
    public static list<Messaging.SingleEmailMessage> emailUnprocessedJobStatus() {
          list<Test_Runner_Job__c> jobs = getUnprocessedJobs();   
          list<Messaging.SingleEmailMessage> messages =emailMethodStatus(jobs);   
              for (Test_Runner_Job__c job : jobs) {
                  job.Processed__c = true;
              }   
          update jobs; 
         return messages;
    }

   public static list<Test_Runner_Job__c> getUnprocessedJobs() {
        return [Select t.Name,
          t.Automated_Test_Run__r.Emails__c,
          t.Automated_Test_Run__r.Email_on_Pass__c,
          t.Automated_Test_Run__r.Name,
          t.Automated_Test_Run__c
          From Test_Runner_Job__c t where Processed__c = false];
   }

//Statistics part

    public Void Calculatepercentage() {
        PastATRdetails='';
        List<ID> TRIDS=New List<ID>();//CH0001
        List<Test_Runner_Job__c> RunningJob =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
        if(RunningJob.size()>0){
            //CH0001_Change_Started           
                for(Automated_Test_Run__c ATSrec:[select id,Query__c ,(Select Name from Test_Runner_Jobs__r) from Automated_Test_Run__c where id=:RunningJob[0].Automated_Test_Run__c]){
                    for(Test_Runner_Job__c TR:ATSrec.Test_Runner_Jobs__r) {
                    TRIDS.add(TR.Name);
                    System.debug(TR.Name);
                    }
                }
                System.debug('ParentJobIDS are'+TRIDS);
                Automated_Test_Run__c PastATR=[select id,Query__c from Automated_Test_Run__c where id=:RunningJob[0].Automated_Test_Run__c order by createdDate DESC limit 1];
                PastATRdetails=PastATR.Query__c;
            integer TotalJobsis   =  [select count() FROM ApexTestQueueItem where ParentJobId in:TRIDS];
            integer CompltedJobsis   =  [select count() FROM ApexTestQueueItem where Status IN ('Completed','Aborted') and ParentJobId in:TRIDS];
            //CH001-End
                if((TotalJobsis>0)&& (CompltedJobsis>0)){
                Percentage=(CompltedJobsis*100)/TotalJobsis;
                System.debug('Total Jobs is'+TotalJobsis+ 'CompltedJobs' +CompltedJobsis+ 'Percentage is'+Percentage);
            }       
        }   
    }
    public List<PieWedgeData> getPieData() {
        List<PieWedgeData> data = new List<PieWedgeData>();
        List<ID> TRIDS=New List<ID>();     
        List<Test_Runner_Job__c> RunningJob =[Select Name,Automated_Test_Run__c,CreatedDate From Test_Runner_Job__c order by CreatedDate desc limit 1];
              if(RunningJob.size()>0){
                //CH0001_Change_Started           
                for(Automated_Test_Run__c ATSrec:[select id,Query__c ,(Select Name from Test_Runner_Jobs__r) from Automated_Test_Run__c where id=:RunningJob[0].Automated_Test_Run__c]){
                    for(Test_Runner_Job__c TR:ATSrec.Test_Runner_Jobs__r) {
                    TRIDS.add(TR.Name);
                    System.debug(TR.Name);
                    }
                }
                System.debug('ParentJobIDS are'+TRIDS);           
                  integer CmpltdPass       = [select count() FROM ApexTestResult WHERE Outcome = 'Pass' and AsyncApexJobId in:TRIDS];
                  integer Failed       = [select count() FROM ApexTestResult WHERE Outcome = 'Fail' and AsyncApexJobId in:TRIDS];
                  integer Queuedjobs   = [select count() FROM ApexTestQueueItem where Status='Queued' and ParentJobId in:TRIDS];
                  integer TotalJobs   =  [select count() FROM ApexTestQueueItem where ParentJobId in:TRIDS];
                //CH0001-END
                        if(Queuedjobs>0){
                        data.add(new PieWedgeData('In Progress'+' '+Queuedjobs, +Queuedjobs));
                        }if(CmpltdPass>0){
                        data.add(new PieWedgeData('Passed'+' '+CmpltdPass, +CmpltdPass));
                        }if(Failed>0){
                        data.add(new PieWedgeData('Fail'+' '+Failed, +Failed));
                        }
               }
        return data;
    }
    // Wrapper class
    public class PieWedgeData {
       public String name { get; set; }
       public Integer data { get; set; }
       public Integer CmpltdPass{ get; set; }
       public Integer Failed{ get; set; }
       public Integer Queuedjobs{ get; set; }
           public PieWedgeData(String name, Integer data) {
                this.name = name;
                this.data = data;
            }
    }
 
    public PageReference Refresh(){
        deleteCompletedJobs();
        Calculatepercentage();
        refreshHasScheduledJobs();
        if(Percentage==100){
                email();                 
            }else{
                hasScheduledJobs = true;
            }                   
        PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
        pageRef.setRedirect(true);
        return pageRef;
    }
    //Scheduling Job run & Email Sending from Auotestrunner class
    // Enqueue all unit test classes as spec'd by Automated_Test_Run__c record(s)
 
//CH0001-updated enqueueTests method
    public static list<ID> enqueueTests() {
        list<Id> jobIds = new list<Id>();
        list<ID> ParenjobIDS= new list<ID>();//CH0001
        List<Test_Runner_Job__c> TRjobs= new List<Test_Runner_Job__c>();//CH0001
       try{
        CronTrigger CurrentShedulejob = [select Id,State,CronJobDetail.Name from CronTrigger where CronJobDetail.JobType = '7' and CronJobDetail.Name like '%AutoTestRunnerAdhoc%' and State in('ACQUIRED','EXECUTING') limit 1];
        //System.debug('Cuurent Shedule Job Name '+CurrentShedulejob[0].CronJobDetail.Name+'Cuurent Shedule Job State is'+CurrentShedulejob[0].State);
        String JobNameis=CurrentShedulejob.CronJobDetail.Name;
        Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        Automated_Test_Run__c EmailRecord=[select Emails__c,Schedule_Name__c from Automated_Test_Run__c where RecordTypeId=:ATEmilRecordTypeId and Schedule_Name__c=:JobNameis  order by createdDate DESC limit 1];
        string whereExcluded = '';
        string Keywordis = '';
        string ATRIDis = '';       
        for (Automated_Test_Run__c run : [select Query__c,Schedule_Name__c,Excluded_Classes__c,
            Email_on_Pass__c, Exclude_Managed_Packages__c
            from Automated_Test_Run__c where Active__c = true and RecordTypeId=:ATERecordTypeId and Schedule_Name__c=:EmailRecord.Schedule_Name__c order by createdDate DESC limit 1]) {
               ATRIDis=run.id;
                if (run.Excluded_Classes__c != null) {
                    for (string c : run.Excluded_Classes__c.split('[,\\s]+')) {
                        whereExcluded += 'and Name != \'' + c + '\'';
                    }
                }
                if (run.Exclude_Managed_Packages__c == True) {
                   whereExcluded += ' AND NameSpacePrefix = null';
                }
                if (run.Query__c != null && run.Query__c != ' ' ) {
                   Keywordis +=run.Query__c;
                }
           }
            string query = 'SELECT Id FROM ApexClass WHERE Name LIKE \'' + Keywordis+ '\' ' + whereExcluded;
            ApexClass[] testClasses = Database.query(query);
           
            if (testClasses.size() > 0) {
                ApexTestQueueItem[] queueItems = new List<ApexTestQueueItem>();
                for (ApexClass cls : testClasses) {
                    queueItems.add(new ApexTestQueueItem(ApexClassId=cls.Id));
                }
                if (!Test.isRunningTest()) {
                    DataBase.insert(queueItems,false);   
                    // Get the job ID of the first queue item returned.

                    //CH0001-Start
                    for(ApexTestQueueItem itm:[SELECT ParentJobId FROM ApexTestQueueItem WHERE Id=:queueItems]){
                        if(!ParenjobIDS.contains(itm.ParentJobId)){
                        System.debug('ParenjobIDS 1********'+ParenjobIDS);
                        ParenjobIDS.add(itm.parentjobid);
                        jobIds.add(itm.parentjobid);
                        }
                    }
                    System.debug('ParenjobIDS 2 is******'+ParenjobIDS);
                    if(ParenjobIDS.size()>0){
                        for(String PIDS:ParenjobIDS){
                            Test_Runner_Job__c TRJ=New Test_Runner_Job__c();
                            TRJ.Name=PIDS;
                            TRJ.Automated_Test_Run__c = EmailRecord.Id;
                            TRjobs.add(TRJ);
                        }
                    }
                    if(TRjobs.size()>0){
                        DataBase.insert(TRjobs,false);
                        List<Test_Runner_Job__c> insertedTRjobs=[select id,Automated_Test_Run__r.Name,Automated_Test_Run__r.Owner.Name,Automated_Test_Run__r.Query__c,Automated_Test_Run__r.Emails__c,Automated_Test_Run__r.Schedule__c from Test_Runner_Job__c where Automated_Test_Run__r.id=:EmailRecord.Id];
                        AdhocTestexecutionStarted(insertedTRjobs);
                    }                                     
                    //insert new Test_Runner_Job__c(Name = ParenjobIDS,ParentJobIDs__c=ParenjobIDS, Automated_Test_Run__c = EmailRecord.Id);
                    //CH0001-END               
                   
                if(ATRIDis!='' && ATRIDis!=null){
                        Automated_Test_Run__c runATRrecd =[select id,Active__c from Automated_Test_Run__c where Id=:ATRIDis limit 1];
                           runATRrecd.Active__c = false;
                           update runATRrecd;
                   }
                 
                }
            } 
       }catch(exception ex){             
                ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,' exception thrown on execution Adhoc job');
                 ApexPages.addMessage(myMsg);
            }         
        return jobIds;
    }

    public static list<Messaging.SingleEmailMessage> emailMethodStatus(list<Test_Runner_Job__c> jobs) {
        set<string> jobNames = new set<string>();
        for (Test_Runner_Job__c job1 : jobs) {
            jobNames.add(job1.Name);
        }   
        ApexTestResult[] results = [SELECT AsyncApexJobId, Outcome, ApexClass.Name, MethodName, Message, StackTrace
                                    FROM ApexTestResult
                                    WHERE AsyncApexJobId in :jobNames];
       
        return emailMethodStatus(jobs, results);
    }
    // Below emailMethodStatus() is updated As part of CH0001 changes
    public static list<Messaging.SingleEmailMessage> emailMethodStatus(list<Test_Runner_Job__c> jobs, ApexTestResult[] results) {
        list<Messaging.SingleEmailMessage> messages = new list<Messaging.SingleEmailMessage>();       
            List<ID> Atsrecs=New List<ID>();
            List<Task> lTask = new List<Task>();
List<attachment> atcmntlist = new List<attachment>();
Blob fileBody;
            //Changes for Get Sandbox Name: Start
            String fullFileURL = System.URL.getSalesforceBaseURL().getHost();
            system.debug(fullFileURL);
            String[] instance = fullFileURL .split('\\.');
            system.debug(instance[0]);
            String SandboxIs=instance[0];
            Organization orgdata=[SELECT IsSandbox FROM Organization Limit 1];
                if(orgdata.IsSandbox){
                    SandboxIs = SandboxIs.replace('firstdata--', '');
                    System.debug('it is a sandbox ie'+SandboxIs);
                }else if(!orgdata.IsSandbox){ 
                    SandboxIs = SandboxIs.replace('firstdata', 'Production');
                    System.debug('it is not a sandbox it is a production ie'+SandboxIs);
                }
            system.debug('Sandbox is***'+SandboxIs);
            //Changes for Get Sandbox Name: END
            for (Test_Runner_Job__c jobmap : jobs) {       
                if(!Atsrecs.contains(jobmap.Automated_Test_Run__c)){
                Atsrecs.add(jobmap.Automated_Test_Run__c);
                }         
               
            }
            System.debug('Automated records **'+Atsrecs);
               
                for(Automated_Test_Run__c ATSrecloop:[select id,Query__c,Emails__c,Name,(Select Name,Automated_Test_Run__r.Email_on_Pass__c,Automated_Test_Run__r.Emails__c,Automated_Test_Run__r.Name,Processed__c from Test_Runner_Jobs__r) from Automated_Test_Run__c where id in:Atsrecs]){
                    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                    integer passed = 0;
                    integer total = 0;
                    string body='';
                    string Resultsare='';
                    string TestResultsare='';
                    boolean allPassed;
                    string ResultsIS='Pass';
                    mail.setToAddresses(ATSrecloop.Emails__c.split('[,\\s]+'));
                    //mail.setSubject(ATSrecloop.Name + ' Automated Test Results: ' + (passed < total ? 'Fail' : 'Pass')); 
                                       
                        for(Test_Runner_Job__c job:ATSrecloop.Test_Runner_Jobs__r) {
                            //for (Test_Runner_Job__c job : jobs) {
                            system.debug('Test Runner Job: Id ' + job.Id + ' Name ' + job.Name);
                            string failTable = '<table border="1" cellpadding="5px">';
                            string className = '';
                           
                            for (ApexTestResult atr : results) {
                                system.debug('Apex Test Result: Id '  + atr.AsyncApexJobId);
                                if ((string)atr.AsyncApexJobId == job.Name || (Test.isRunningTest() && jobs.size() == 1)) {
                                    if (atr.Outcome == 'Pass') {
                                        passed++;
                                    } else {
                                        ResultsIS='Fail';
                                        if (atr.ApexClass.Name != className) {
                                            className = atr.ApexClass.Name;
                                            failTable += '<tr style="background: #ddd; font-weight: bold;"><td colspan="2">' + className + '</td></tr>\n';
                                        }
                                        failTable += '<tr><td>' + atr.MethodName + '</td><td> ' + atr.message + '</td></tr>\n';
                                    }
                                    total++;
                                }
                            }
                       
                            failTable += '</table>';
                       
                            Resultsare = '<p>' + passed + '/' + total + ' tests passed</p>\n';
                            TestResultsare= passed + '/' + total + ' tests passed';
                            allPassed = passed == total;
                       
                            if (!allPassed) {
                                //body += '<p>Test Failures:</p>\n' + failTable;
                                body += failTable;
                            }

                        }
                        mail.setSubject(SandboxIs+'_'+ATSrecloop.Name + ' Automated Test Results: ' + ResultsIS); //CH0001
                       
                        for(Test_Runner_Job__c job:ATSrecloop.Test_Runner_Jobs__r){
                                if ((allPassed && job.Automated_Test_Run__r.Email_on_Pass__c) || !allPassed) {
                                    mail.setHtmlBody(Resultsare+body);
fileBody=blob.valueOf(body);
//fileBody=Blob.topdf('body');
                                    System.debug(mail);                               
                                }
                            }
                    messages.add(mail);
                            //Task Creation-CH0001
                                Task t = new Task();
                                t.WhatId = ATSrecloop.id;
                                t.Subject = 'Test execution summary - Org:'+SandboxIs+'-'+ATSrecloop.Name;
                                t.Priority = 'Normal';
                                t.Status = 'Completed';
                                t.Description=TestResultsare;
                                t.Type = 'Action';
                                lTask.add(t); 

Attachment attachment = new Attachment();
//attachment.Body = fileBody;
attachment.Body = fileBody;
//attachment.Name = 'Test execution summary'+'.txt.enc';
attachment.Name = 'Test execution summary'+'.doc';
attachment.ParentId = ATSrecloop.id;
atcmntlist.add(attachment);
                } 

        if (!Test.isRunningTest()) {
            //Messaging.sendEmail(messages);************
        }
         if(!lTask.IsEmpty()){
                insert lTask;
           }
if(!atcmntlist.IsEmpty()){
insert atcmntlist;
}  
        return messages;
    }
   //CH0001 -Start       
    //Recuurence procedure Starts----
 
     public PageReference RecuureceATSinsertandSchedule(){
       
        reccurenceMsg=false;
        List<Automated_Test_Run__c> ATSrecinsert=New List<Automated_Test_Run__c>();
        deleteCompletedJobs();
        String randomnumberis=generateRandomNumber();
        //String RecrnceKeyword='%Test%';
        String RecrnceKeyword=System.Label.AutomatedRecurrenceKeyword;
         System.debug('***RecrnceKeyword is***'+RecrnceKeyword);
        String ScheduleNameis='AutoTestRunnerRecurrence_'+RecrnceKeyword+'_'+randomnumberis;
        AtrRecord.Query__c=RecrnceKeyword;
        AtrRecord.Excluded_Classes__c=AtrRecord.Excluded_Classes__c;
        AtrRecord.Exclude_Managed_Packages__c=AtrRecord.Exclude_Managed_Packages__c;
     
        AtrRecord.Frequency__c=AtrRecord.Frequency__c;
        AtrRecord.On_Every__c=AtrRecord.On_Every__c;
        AtrRecord.Start_Date__c=AtrRecord.Start_Date__c;
        AtrRecord.End_Date__c=AtrRecord.End_Date__c;
        AtrRecord.Schedule_Name__c= ScheduleNameis;
        AtrRecord.Preferred_Time__c=AtrRecord.Preferred_Time__c;
     
        AtrRecord.RecordTypeId=ATERecordTypeId;
        ATSrecinsert.add(AtrRecord);
     
        Automated_Test_Run__c ATEemail = new Automated_Test_Run__c();
        ATEemail.Query__c=RecrnceKeyword;
        ATEemail.Emails__c=AtrRecord.Emails__c;
        ATEemail.Email_on_Pass__c=AtrRecord.Email_on_Pass__c;
        //CH0001_Start
        ATEemail.Frequency__c=AtrRecord.Frequency__c;
        ATEemail.On_Every__c=AtrRecord.On_Every__c;
        ATEemail.Start_Date__c=AtrRecord.Start_Date__c;
        ATEemail.End_Date__c=AtrRecord.End_Date__c;
        ATEemail.Schedule_Name__c= ScheduleNameis ;
        ATEemail.Preferred_Time__c=AtrRecord.Preferred_Time__c;
        //CH0001_END
        ATEemail.RecordTypeId=ATEmailRecordTypeId;
        ATSrecinsert.add(ATEemail);
        Savepoint sp = Database.setSavepoint();
        System.debug('Inserting record is Query'+AtrRecord.Query__c +'Frequency__c is'+AtrRecord.Frequency__c+ 'On_Every__c is'+AtrRecord.On_Every__c+'Start_Date__c is'+AtrRecord.Start_Date__c+'End_Date__c is'+AtrRecord.End_Date__c +'Preferred_Time__c'+AtrRecord.Preferred_Time__c);
        Date StartDateis=AtrRecord.Start_Date__c;
        Date EndDateis=AtrRecord.End_Date__c;
        //Validation here
        reccurenceMsg=validateDates(StartDateis,EndDateis);
        if(reccurenceMsg==false){
            Integer Startyearis=StartDateis.year();
            Integer Endyearis=EndDateis.year();
            Integer StartmonthNum =StartDateis.month();
            Integer EndmonthNum = EndDateis.month();
            Map <Integer,String> monthNumbers = new Map <Integer,String> {1=>'Jan', 2=>'Feb',3=>'Mar',4=>'Apr', 5=>'May', 6=>'Jun',7=>'Jul',8=>'Aug', 9=>'Sep', 10=>'Oct', 11=>'Nov', 12=>'Dec'};
            String StartMonth=monthNumbers.get(StartmonthNum);
            String EndMonth=monthNumbers.get(EndmonthNum);
            string gvnDateis='?';
            //String Dateis='?';
            String Shddayofmonth='?';
            String Dayofweek='?';
            string Months=StartMonth+'-'+EndMonth;
            string Years=Startyearis+'-'+Endyearis;
            try{
                if(AtrRecord.Frequency__c=='Monthly'){
                    gvnDateis=AtrRecord.On_Every__c;
                    //Date gvnDateis=date.parse(inputDate);
                     //gvnDateis = String.valueOf(StartDateis.day());           
                    } else if(AtrRecord.Frequency__c=='Weekly'){
                    Dayofweek=AtrRecord.On_Every__c;
                    //gvnDateis = String.valueOf(StartDateis.day());             
                }
               String formatedDates=gvnDateis.replaceAll(';', ',');
               String formatedDayofweek=Dayofweek.replaceAll(';', ',');
               
                    Map<String,string> Hoursformat=new Map<String,String> {'01:00 AM'=>'1','02:00 AM'=>'2','03:00 AM'=>'3','04:00 AM'=>'4','05:00 AM'=>'5','06:00 AM'=>'6','07:00 AM'=>'7',
                    '08:00 AM'=>'8','09:00 AM'=>'9','10:00 AM'=>'10','11:00 AM'=>'11','12:00 PM'=>'12','01:00 PM'=>'13','02:00 PM'=>'14','03:00 PM'=>'15','04:00 PM'=>'16','05:00 PM'=>'17',
                    '06:00 PM'=>'18','07:00 PM'=>'19','08:00 PM'=>'20','09:00 PM'=>'21','10:00 PM'=>'22','11:00 PM'=>'23','12:00 PM'=>'0'};

                    Map <String,String> DAYformat = new Map <String,String> {'SUNDAY'=>'SUN', 'MONDAY'=>'MON','TUESDAY'=>'TUE','WEDNESDAY'=>'WED','THURSDAY'=>'THU', 'FRIDAY'=>'FRI','SATURDAY'=>'SAT'};

                    String GetHour=Hoursformat.get(AtrRecord.Preferred_Time__c);
                    System.debug('***GetHour is***'+GetHour);
                    System.debug('***formatedDates is***'+formatedDates);
                    System.debug('***Months is***'+Months);
                    System.debug('***Dayofweek is***'+Dayofweek);
                    System.debug('***yearis is***'+Years);
                 
                    //Seconds   Minutes Hours   Day Of Month    Month   Day Of Week Year
                    String strSchedule = '0 ' + '0 '+GetHour+ ' ' +formatedDates+ ' ' +Months+ ' ' +formatedDayofweek+ ' ' + Years;
                    System.debug('***strSchedule***'+strSchedule);
                   AutoTestRunnerRecurrence.setup(strSchedule,ScheduleNameis);

                        upsert ATSrecinsert;             
                       
            }
            catch(exception ex){
                Database.rollback(sp);
                ApexPages.addMessages(ex);
                reccurenceMsg=true;
               
            }
        }
        PageReference pageRef;
        System.debug('reccurenceMsg is '+reccurenceMsg);
        System.debug('pageRef is '+pageRef);
        if(reccurenceMsg==true && reccurenceMsg!=false){
            pageRef=null;         
        }else if(reccurenceMsg==false){         
            pageRef = new PageReference('/apex/AutomatedTestSetupRecurrence');
                    pageRef.setRedirect(true);
                    return pageRef;
        }
         System.debug('reccurenceMsg is 2'+reccurenceMsg);
        System.debug('pageRef is 2 '+pageRef);                       
     return pageRef;
    }
 
    public boolean validateDates(date StartDateis,date EndDateis) {
        reccurenceMsg=false;
        date today= date.today();
        if(StartDateis>=EndDateis){
            reccurenceMsg=true;                   
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,'Start Date cannot be less than End Date and also both dates not same');
            ApexPages.addMessage(myMsg);
        } else if(StartDateis < today ){
            reccurenceMsg=true;
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,'Start Date Must be Greater than Today');
            ApexPages.addMessage(myMsg);
        }else if(EndDateis < today ){
            reccurenceMsg=true;
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,'End Date Must be Greater than Today');
            ApexPages.addMessage(myMsg);
        }
        return reccurenceMsg;
    }
    public void refreshHasRecrnsScheduledJobs() {
        List<CronTrigger> recurnceSchdjobs=New  List<CronTrigger>();
        integer jobCount = [SELECT count() FROM CronTrigger  where CronJobDetail.Name like '%AutoTestRunnerRecurrence%'];
        recurnceSchdjobs=[SELECT CronJobDetail.Name,CreatedDate,NextFireTime,State FROM CronTrigger where CronJobDetail.Name like '%AutoTestRunnerRecurrence%' and State in('WAITING','ACQUIRED','EXECUTING')];
        if(recurnceSchdjobs.size()>0){
            Jobstatus=recurnceSchdjobs[0].State;
            if(recurnceSchdjobs[0].NextFireTime!=null ){
            Datetime shddatetimeGSt=recurnceSchdjobs[0].NextFireTime;
            Datetime gmt = shddatetimeGSt;
             String timeZone = UserInfo.getTimeZone().getID();
             Datetime GivenDateTime=shddatetimeGSt;// here you can user your dates e.g. createddate
              Datetime localdt=Datetime.valueOf(GivenDateTime);
              //showdatetime = string.valueOfGmt(local);
              shddatetime=localdt.format();
              }
              else if(Jobstatus!=null && Jobstatus!='') {
                  shddatetime='Test Scheduled Job Current State is '+Jobstatus;
              }
            }         
        hasRecScheduledJobs = jobCount !=0;       
    }
    public PageReference CancelRecurrenceJobs() { 
          List<CronTrigger> jobsToAbort = [select Id from CronTrigger where CronJobDetail.JobType = '7' and CronJobDetail.Name like '%AutoTestRunnerRecurrence%'];
              if(jobsToAbort.size()>0){
                  for (CronTrigger job : jobsToAbort) {
                   System.abortJob(job.Id);
                   }
               }
               PageReference pageRef = new PageReference('/apex/AutomatedTestSetupRecurrence');
                    pageRef.setRedirect(true);
                    return pageRef;
    }
 
    public static list<ID> recurrenceenqueueTests() {
        list<Id> jobIds = new list<Id>();
        list<ID> ParenjobIDS= new list<ID>();//CH0001
        List<Test_Runner_Job__c> TRjobs= new List<Test_Runner_Job__c>();//CH0001
        Try{       
        Id ATERecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Execution').getRecordTypeId();
        Id ATEmilRecordTypeId = Schema.SObjectType.Automated_Test_Run__c.getRecordTypeInfosByName().get('Automated Test Email Notification').getRecordTypeId();
        Automated_Test_Run__c EmailRecord=[select Emails__c,Schedule_Name__c from Automated_Test_Run__c where RecordTypeId=:ATEmilRecordTypeId and Schedule_Name__c like '%AutoTestRunnerRecurrence%' order by createdDate DESC limit 1];
        string whereExcluded = '';
        string Keywordis = '';
        string ATRIDis = '';
        for (Automated_Test_Run__c run : [select Query__c, Excluded_Classes__c,
            Email_on_Pass__c, Exclude_Managed_Packages__c
            from Automated_Test_Run__c where Active__c = true and RecordTypeId=:ATERecordTypeId and Frequency__c!=null and Schedule_Name__c=:EmailRecord.Schedule_Name__c  order by createdDate DESC limit 1]) {
               ATRIDis=run.id;
                if (run.Excluded_Classes__c != null) {
                    for (string c : run.Excluded_Classes__c.split('[,\\s]+')) {
                        whereExcluded += 'and Name != \'' + c + '\'';
                    }
                }
                if (run.Exclude_Managed_Packages__c == True) {
                   whereExcluded += ' AND NameSpacePrefix = null';
                }
                if (run.Query__c != null && run.Query__c != ' ' ) {
                   Keywordis +=run.Query__c;
                }
           }
            string query = 'SELECT Id FROM ApexClass WHERE Name LIKE \'' + Keywordis+ '\' ' + whereExcluded;
            ApexClass[] testClasses = Database.query(query);
           
            if (testClasses.size() > 0) {
                ApexTestQueueItem[] queueItems = new List<ApexTestQueueItem>();
                for (ApexClass cls : testClasses) {
                    queueItems.add(new ApexTestQueueItem(ApexClassId=cls.Id));
                }
                if (!Test.isRunningTest()) {
                    DataBase.insert(queueItems,false);   
                    // Get the ParentJob IDS from Apex Test Queue Items.
                    //CH0001-Start
                    for(ApexTestQueueItem itm:[SELECT ParentJobId FROM ApexTestQueueItem WHERE Id=:queueItems]){
                        if(!ParenjobIDS.contains(itm.ParentJobId)){
                        System.debug('ParenjobIDS 1********'+ParenjobIDS);
                        ParenjobIDS.add(itm.parentjobid);
                        jobIds.add(itm.parentjobid);
                        }
                    }
                    System.debug('ParenjobIDS 2 is******'+ParenjobIDS);
                    if(ParenjobIDS.size()>0){
                        for(String PIDS:ParenjobIDS){
                            Test_Runner_Job__c TRJ=New Test_Runner_Job__c();
                            TRJ.Name=PIDS;
                            TRJ.Automated_Test_Run__c = EmailRecord.Id;
                            TRjobs.add(TRJ);
                        }
                    }
                    if(TRjobs.size()>0){
                        DataBase.insert(TRjobs,false);
                        List<Test_Runner_Job__c> insertedTRjobs=[select id,Automated_Test_Run__r.Name,Automated_Test_Run__r.Owner.Name,Automated_Test_Run__r.Frequency__c,
                                                                    Automated_Test_Run__r.Query__c,Automated_Test_Run__r.Emails__c,Automated_Test_Run__r.On_Every__c,Automated_Test_Run__r.Start_Date__c,Automated_Test_Run__r.End_Date__c,Automated_Test_Run__r.Schedule__c from Test_Runner_Job__c where Automated_Test_Run__r.id=:EmailRecord.Id];
                        RecuurenceTestexecutionStarted(insertedTRjobs);
                    }                                     
                    //insert new Test_Runner_Job__c(Name = ParenjobIDS,ParentJobIDs__c=ParenjobIDS, Automated_Test_Run__c = EmailRecord.Id);
                    //CH0001-END 
                   // ApexTestQueueItem item =[SELECT ParentJobId FROM ApexTestQueueItem WHERE Id=:queueItems[0].Id LIMIT 1];                 
                    //insert new Test_Runner_Job__c(Name = item.parentjobid, Automated_Test_Run__c = EmailRecord.Id);
                    //jobIds.add(item.parentjobid);             
                }
            }
            }
            catch(exception ex){             
                ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.INFO,' exception thrown on execution Recuurence job');
                 ApexPages.addMessage(myMsg);
            }
        return jobIds;
    }
    public PageReference click(){
        System.debug('isChecked is ' +isChecked);
        PageReference pageRef;
         if(isChecked!=TRUE){
             isCheckedRec = true;
             System.debug('isCheckedRec is ' +isCheckedRec);
        pageRef = new PageReference('/apex/AutomatedTestSetupRecurrence');
         }
         else{
             isCheckedRec = false;
             pageRef = new PageReference('/apex/AutomatedTestSetup');
         }     
                    pageRef.setRedirect(true);
                    return pageRef;
         //return null;
     }
   
   public PageReference Adhocclick(){
    System.debug('isAdhocChecked is ' +isAdhocChecked);
    PageReference pageRef;
         if(isAdhocChecked!=TRUE){
             isAdhocChecked = true;
             System.debug('isAdhocChecked is ' +isAdhocChecked);
        pageRef = new PageReference('/apex/AutomatedTestSetupAdhoc');
         }
         else{
             isCheckedRec = false;
             pageRef = new PageReference('/apex/AutomatedTestSetupRecurrence');
         }     
                    pageRef.setRedirect(true);
                    return pageRef;
         //return null;
     }
     
   public static String generateRandomNumber(){     
       Decimal randomValue = 100000 * math.random();     
       String userCode = String.valueOf(randomValue);     
       userCode = userCode.substring(0,3);     
       return userCode;   
       }
     
    //multipleAdhocJobs

  public PageReference CancelAdhocJobs() { 
    System.debug('SelectedAdhocJobId is'+SelectedAdhocJobId); 
      for(CronTrigger a : Schdjobs){
           if (a.Id == SelectedAdhocJobId) {
            System.abortJob(a.Id);
            }
       } 

       PageReference pageRef = new PageReference('/apex/AutomatedTestSetup');
       pageRef.setRedirect(true);
      return pageRef;
  }
 
  public void ScheduledJobs() {       
        Schdjobs=[SELECT CronJobDetail.Name,CreatedDate,TimesTriggered,NextFireTime,State FROM CronTrigger where CronJobDetail.Name like '%AutoTestRunner%' and State in('WAITING','ACQUIRED','EXECUTING')];         
    }
 
  //Execution Started Email fairinig methods--CH0001 Stared
 
    public Static void AdhocTestexecutionStarted( List<Test_Runner_Job__c> TRjobs){
         boolean run = true;
        List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        //Changes for Get Sandbox Name: Start
        String fullFileURL = System.URL.getSalesforceBaseURL().getHost();
        system.debug(fullFileURL);
        String[] instance = fullFileURL .split('\\.');
        system.debug(instance[0]);
        String SandboxIs=instance[0];
        Organization orgdata=[SELECT IsSandbox FROM Organization Limit 1];
            if(orgdata.IsSandbox){
                SandboxIs = SandboxIs.replace('firstdata--', '');
                System.debug('it is a sandbox ie'+SandboxIs);
            }else if(!orgdata.IsSandbox){ 
                SandboxIs = SandboxIs.replace('firstdata', 'Production');
                System.debug('it is not a sandbox it is a production ie'+SandboxIs);
            }
        system.debug('Sandbox is***'+SandboxIs);
        //Changes for Get Sandbox Name: END
        if(TRjobs.Size()>0){
            for(Test_Runner_Job__c TJmail:TRjobs){
                    if(run){
                        mail.setToAddresses(TJmail.Automated_Test_Run__r.Emails__c.split('[,\\s]+'));
                        //mail.setSubject(TJmail.Automated_Test_Run__r.Name + '  Adhoc Automated Test Execution Started ' + TJmail.Automated_Test_Run__r.Query__c+''+TJmail.Automated_Test_Run__r.Schedule__c);
                         mail.setSubject(SandboxIs+'_'+TJmail.Automated_Test_Run__r.Name + '  Adhoc Automated Test Execution Started ' + TJmail.Automated_Test_Run__r.Query__c+''+TJmail.Automated_Test_Run__r.Schedule__c);
                         String sHtmlBody1='Hi'+' '+TJmail.Automated_Test_Run__r.Owner.Name+' ,<br/><br/>'+'The below  Adhoc Automated Test Execution is Started now :<br/><br/>';
                                  //sHtmlBody1+='<a href='+URL.getSalesforceBaseUrl().toExternalForm()+'/'+TJmail.Automated_Test_Run__r.id+'>';
                                  sHtmlBody1+='Keyword: </a>'+TJmail.Automated_Test_Run__r.Query__c+'<br/>';
                                  sHtmlBody1+='Emails: </a>'+TJmail.Automated_Test_Run__r.Emails__c+'<br/>';
                                  sHtmlBody1+='Schedule Time: </a>'+TJmail.Automated_Test_Run__r.Schedule__c+'<br/>';
                                  sHtmlBody1+='Org: </a>'+SandboxIs+'<br/><br/>';
                                  sHtmlBody1+='<a href='+System.URL.getSalesforceBaseUrl().toExternalForm()+'/'+TJmail.Automated_Test_Run__r.id+'>'+'<br/>';
                                  sHtmlBody1+='Click here to go to Automated Test Run Record<br/><br/>';
                                  //sHtmlBody1+='Thank You<br/>';
                                  mail.setHtmlBody(sHtmlBody1);
                                   mails.add(mail);
                                   run=false;                 
                                Messaging.sendEmail(mails);
                    }
            }
        }
    }
   
    public Static void RecuurenceTestexecutionStarted( List<Test_Runner_Job__c> TRjobs){
         boolean run = true;
        List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        //Changes for Get Sandbox Name: Start
        String fullFileURL = System.URL.getSalesforceBaseURL().getHost();
        system.debug(fullFileURL);
        String[] instance = fullFileURL .split('\\.');
        system.debug(instance[0]);
        String SandboxIs=instance[0];
        Organization orgdata=[SELECT IsSandbox FROM Organization Limit 1];
            if(orgdata.IsSandbox){
                SandboxIs = SandboxIs.replace('firstdata--', '');
                System.debug('it is a sandbox ie'+SandboxIs);
            }else if(!orgdata.IsSandbox){ 
                SandboxIs = SandboxIs.replace('firstdata', 'Production');
                System.debug('it is not a sandbox it is a production ie'+SandboxIs);
            }
        system.debug('Sandbox is***'+SandboxIs);
        //Changes for Get Sandbox Name: END
        if(TRjobs.Size()>0){
                for(Test_Runner_Job__c TJmail:TRjobs){
                        if(run){
                            // mail.setToAddresses(TJmail.Automated_Test_Run__r.Emails__c.split('[,]+'));
                             mail.setToAddresses(TJmail.Automated_Test_Run__r.Emails__c.split('[,\\s]+'));
                            //mail.setSubject(TJmail.Automated_Test_Run__r.Name + ' Recurrence Automated Test Execution Started '+''+ TJmail.Automated_Test_Run__r.Query__c);
                            mail.setSubject(SandboxIs+'_'+TJmail.Automated_Test_Run__r.Name + ' Recurrence Automated Test Execution Started '+''+ TJmail.Automated_Test_Run__r.Query__c);
                             String sHtmlBody1='Hi'+' '+TJmail.Automated_Test_Run__r.Owner.Name+' ,<br/><br/>'+'The below  Recurrence Automated Test Execution is Started now :<br/><br/>';
                                      //sHtmlBody1+='<a href='+URL.getSalesforceBaseUrl().toExternalForm()+'/'+TJmail.Automated_Test_Run__r.id+'>';
                                      sHtmlBody1+='Keyword: </a>'+TJmail.Automated_Test_Run__r.Query__c+'<br/>';
                                      sHtmlBody1+='Emails: </a>'+TJmail.Automated_Test_Run__r.Emails__c+'<br/>';
                                      sHtmlBody1+='Frequency: </a>'+TJmail.Automated_Test_Run__r.Frequency__c+'<br/>';
                                      sHtmlBody1+='On Every: </a>'+TJmail.Automated_Test_Run__r.On_Every__c+'<br/>';
                                      sHtmlBody1+='Start Date: </a>'+TJmail.Automated_Test_Run__r.Start_Date__c+'<br/>';
                                      sHtmlBody1+='End Date: </a>'+TJmail.Automated_Test_Run__r.End_Date__c+'<br/>';
                                      sHtmlBody1+='Org: </a>'+SandboxIs+'<br/><br/>';                                   
                                      sHtmlBody1+='<a href='+System.URL.getSalesforceBaseUrl().toExternalForm()+'/'+TJmail.Automated_Test_Run__r.id+'>'+'<br/>';
                                      sHtmlBody1+='Click here to go to Automated Test Run Record<br/><br/>';
                                      //sHtmlBody1+='Thank You<br/>';
                                      mail.setHtmlBody(sHtmlBody1);
                                       mails.add(mail);
                                       run=false;                 
                                   Messaging.sendEmail(mails);
                             }
                }
        }
    }
  //Execution Started Email fairinig methods--CH0001 End
    //CH0001 -End
}