public static ComparisonResult IsEqualTo(this IElementNavigator expected, IElementNavigator actual)
        {
            if (!namesEqual(expected.Name, actual.Name))
            {
                return(ComparisonResult.Fail(actual.Location, $"name: was '{actual.Name}', expected '{expected.Name}'"));
            }
            if (!valuesEqual(expected.Value, actual.Value))
            {
                return(ComparisonResult.Fail(actual.Location, $"value: was '{actual.Value}', expected '{expected.Value}'"));
            }

            // Allow the expected navigator to have more type info than the actual navigator
            if (expected.Type != actual.Type && actual.Type != null)
            {
                return(ComparisonResult.Fail(actual.Location, $"type: was '{actual.Type}', expected '{expected.Type}'"));
            }
            if (expected.Location != actual.Location)
            {
                ComparisonResult.Fail(actual.Location, $"location: was '{actual.Location}', expected '{expected.Location}'");
            }

            // Ignore ordering (only relevant to xml)
            var childrenExp    = expected.Children().OrderBy(e => e.Name);
            var childrenActual = actual.Children().OrderBy(e => e.Name).GetEnumerator();

            // Don't compare lengths, as this would require complete enumeration of both collections
            // just enumerate through the lists, comparing each item as they go.
            // first fail (or list end) will drop out.
            foreach (var exp in childrenExp)
            {
                if (!childrenActual.MoveNext())
                {
                    ComparisonResult.Fail(actual.Location, $"number of children was different");
                }

                var result = exp.IsEqualTo(childrenActual.Current);
                if (!result.Success)
                {
                    return(result);
                }
            }
            if (childrenActual.MoveNext())
            {
                ComparisonResult.Fail(actual.Location, $"number of children was different");
            }

            return(ComparisonResult.OK);

            bool valuesEqual(object e, object a)
            {
                string eVal = e != null?PrimitiveTypeConverter.ConvertTo <string>(e) : null;

                string aVal = a != null?PrimitiveTypeConverter.ConvertTo <string>(a) : null;

                return(eVal == aVal);
            }

            bool namesEqual(string e, string a) => e == a || (a != null && e != null && (a.StartsWith(e)));
        }
        public static ComparisonResult IsEqualTo(this IElementNavigator expected, IElementNavigator actual)
        {
            if (!valuesEqual(expected.Value, actual.Value))
            {
                return(ComparisonResult.Fail(actual.Location, $"value: was '{actual.Value}', expected '{expected.Value}'"));
            }
            if (!namesEqual(expected.Name, actual.Name))
            {
                return(ComparisonResult.Fail(actual.Location, $"name: was '{actual.Name}', expected '{expected.Name}'"));
            }

            // Allow the expected navigator to have more type info than the actual navigator
            if (expected.Type != actual.Type && actual.Type != null)
            {
                return(ComparisonResult.Fail(actual.Location, $"type: was '{actual.Type}', expected '{expected.Type}'"));
            }
            if (expected.Location != actual.Location)
            {
                ComparisonResult.Fail(actual.Location, $"location: was '{actual.Location}', expected '{expected.Location}'");
            }

            // Ignore ordering (only relevant to xml)
            var childrenExp    = expected.Children().OrderBy(e => e.Name).ToArray();
            var childrenActual = actual.Children().OrderBy(e => e.Name).ToArray();

            if (childrenExp.Length != childrenActual.Length)
            {
                ComparisonResult.Fail(actual.Location, $"number of children was {childrenActual.Length}, expected {childrenExp.Length}");
            }

            for (var index = 0; index < childrenExp.Length; index++)
            {
                var result = childrenExp[index].IsEqualTo(childrenActual[index]);
                if (!result.Success)
                {
                    return(result);
                }
            }

            return(ComparisonResult.OK);

            bool valuesEqual(object e, object a)
            {
                string eVal = e != null?PrimitiveTypeConverter.ConvertTo <string>(e) : null;

                string aVal = a != null?PrimitiveTypeConverter.ConvertTo <string>(a) : null;

                return(eVal == aVal);
            }

            bool namesEqual(string e, string a) => e == a || (a != null && e != null && (a.StartsWith(e)));
        }