private TestResult ProcessTsTestResult(TsTestResult tsTestResult, TestCase vsTestCase)
        {
            Log("RunJavaScriptTests() called");

            // init result object
            TestResult vsResult = new TestResult(vsTestCase);

            vsResult.DisplayName  = vsTestCase.DisplayName;
            vsResult.ComputerName = Environment.MachineName;
            vsResult.Outcome      = tsTestResult.testOutcome;
            vsResult.StartTime    = tsTestResult.startTime;
            vsResult.EndTime      = tsTestResult.endTime;
            vsResult.Duration     = new TimeSpan(tsTestResult.durationMs * 10000);

            switch (vsResult.Outcome)
            {
            case TestOutcome.Passed:
                vsResult.ErrorMessage = "Test passed successfully";
                break;

            case TestOutcome.Skipped:
                break;                         // do nothing

            case TestOutcome.None:
                Log($"TestOutcome.None for test {vsResult.TestCase.FullyQualifiedName}");
                break;

            case TestOutcome.NotFound:
                Log($"TestOutcome.NotFound for test {vsResult.TestCase.FullyQualifiedName}");
                break;

            case TestOutcome.Failed:
                // test failed
                vsResult.ErrorMessage    = tsTestResult.errorMessage;
                vsResult.ErrorStackTrace = tsTestResult.errorStackTrace;

                string fullFilename = vsResult.TestCase.Source;
                string filename     = Path.GetFileName(fullFilename);

                // this method can handle both .js and .ts files
                int line = SourcePos.GetErrorPosFromStackTrace(fullFilename, tsTestResult.errorStackTrace).Line;

                // get function name from stack trace
                Regex  regex    = new Regex("[A-Za-z0-9]+");
                Match  match    = regex.Match(vsResult.ErrorStackTrace.Substring(7));
                string function = match.Value;

                // thank-you denvercoder9 (aka Moe Seth)
                // https://social.msdn.microsoft.com/Forums/vstudio/en-US/3be3175d-dce1-48bc-9ffe-10627d99962c/questions-to-unit-test-explorer-gurus-errorstacktrace?forum=vstest
                // "at testMethod1 in C:\TestingProject\UnitTest1\UnitTest1\test.js:line 9"
                vsResult.ErrorStackTrace = $"at {function}() in {fullFilename}:line {line}";
                break;
            }

            Log("...finished checking test results for requested test");

            return(vsResult);
        }
        TestCase FindVsTestResult(TsTestResult tsTestResult, IEnumerable <TestCase> vsTests)
        {
            //Log($"Looking for test {tsTestResult.displayName} from file {tsTestResult.testFilename} among the {vsTests.Count()} vsTests");

            foreach (TestCase vsTestCase in vsTests)
            {
                if (tsTestResult.testFilename == vsTestCase.Source && tsTestResult.displayName == vsTestCase.DisplayName)
                {
                    return(vsTestCase);
                }
            }

            // not found
            Log($"Unable to find test cases for test result, test result='{tsTestResult.displayName}' in file {tsTestResult.testFilename}");
            Log("VS Test case list is as follows:");
            foreach (TestCase vsTestCase in vsTests)
            {
                Log($"filename={vsTestCase.Source} test name = {vsTestCase.DisplayName}");
            }

            return(null);
        }