/// <summary> /// The CSS selector element matcher. /// </summary> public static IEnumerable <Comparison> Match(IDiffContext context, SourceCollection controlSources, SourceCollection testSources) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (controlSources is null) { throw new ArgumentNullException(nameof(controlSources)); } if (testSources is null) { throw new ArgumentNullException(nameof(testSources)); } foreach (var control in controlSources.GetUnmatched()) { if (control.Node.TryGetAttrValue(DIFF_MATCH_ATTR_NAME, out string cssSelector)) { if (TryGetTestNode(context, cssSelector, out var testNode)) { var test = new ComparisonSource(testNode, ComparisonSourceType.Test); yield return(new Comparison(control, test)); } } } yield break; }
/// <summary> /// The post fixed attribute matcher. /// </summary> public static IEnumerable <AttributeComparison> Match(IDiffContext context, SourceMap controlSources, SourceMap testSources) { if (controlSources is null) { throw new ArgumentNullException(nameof(controlSources)); } if (testSources is null) { throw new ArgumentNullException(nameof(testSources)); } foreach (var control in controlSources.GetUnmatched()) { var ctrlName = control.Attribute.Name; if (!NameHasPostfixSeparator(ctrlName)) { continue; } ctrlName = RemovePostfixFromName(ctrlName); if (testSources.Contains(ctrlName) && testSources.IsUnmatched(ctrlName)) { yield return(new AttributeComparison(control, testSources[ctrlName])); } } yield break; }
/// <summary> /// The one to one node matcher. /// </summary> public static IEnumerable <Comparison> Match(IDiffContext context, SourceCollection controlSources, SourceCollection testSources) { if (controlSources is null) { throw new ArgumentNullException(nameof(controlSources)); } if (testSources is null) { throw new ArgumentNullException(nameof(testSources)); } using var controlsEnumerator = controlSources.GetUnmatched().GetEnumerator(); using var testsEnumerator = testSources.GetUnmatched().GetEnumerator(); var hasNextControl = controlsEnumerator.MoveNext(); var hasNextTest = testsEnumerator.MoveNext(); while (hasNextControl && hasNextTest) { yield return(new Comparison(controlsEnumerator.Current, testsEnumerator.Current)); hasNextControl = controlsEnumerator.MoveNext(); hasNextTest = testsEnumerator.MoveNext(); } }
/// <summary> /// The forward searching node matcher strategy. /// </summary> public static IEnumerable <Comparison> Match(IDiffContext context, SourceCollection controlSources, SourceCollection testSources) { if (controlSources is null) { throw new ArgumentNullException(nameof(controlSources)); } if (testSources is null) { throw new ArgumentNullException(nameof(testSources)); } var lastMatchedTestNodeIndex = -1; foreach (var control in controlSources.GetUnmatched()) { var comparison = TryFindMatchingNodes(control, testSources, lastMatchedTestNodeIndex + 1); if (comparison.HasValue) { yield return(comparison.Value); lastMatchedTestNodeIndex = comparison.Value.Test.Index; } } yield break; }
private static IEnumerable <AttributeComparison> AttributeNameMatcher(IDiffContext context, SourceMap controlAttrs, SourceMap testAttrs) { foreach (var ctrlAttrSrc in controlAttrs) { if (testAttrs.Contains(ctrlAttrSrc.Attribute.Name)) { yield return(new AttributeComparison(ctrlAttrSrc, testAttrs[ctrlAttrSrc.Attribute.Name])); } } }
private static bool TryGetTestNode(IDiffContext context, string cssSelector, [NotNullWhen(true)] out INode?testNode) { var searchResult = context.QueryTestNodes(cssSelector); testNode = searchResult.Length switch { 0 => null, 1 => searchResult[0], _ => throw new DiffMatchSelectorReturnedTooManyResultsException($@"The CSS selector ""{cssSelector}"" returned {searchResult.Length} matches from the test node tree. No more than one is allowed.") }; return(testNode is { });
/// <inheritdoc/> public IEnumerable <AttributeComparison> Match(IDiffContext context, SourceMap controlAttrSources, SourceMap testAttrSources) { foreach (var matcher in _attrsMatchers) { foreach (var comparison in matcher(context, controlAttrSources, testAttrSources)) { controlAttrSources.MarkAsMatched(comparison.Control); testAttrSources.MarkAsMatched(comparison.Test); yield return(comparison); } } }
/// <inheritdoc/> public IEnumerable <Comparison> Match(IDiffContext context, SourceCollection controlSources, SourceCollection testSources) { foreach (var matcher in _nodeMatchers) { foreach (var comparison in matcher(context, controlSources, testSources)) { controlSources.MarkAsMatched(comparison.Control); testSources.MarkAsMatched(comparison.Test); yield return(comparison); } } }
/// <summary> /// Attribute name matcher strategy. /// </summary> public static IEnumerable <AttributeComparison> Match(IDiffContext context, SourceMap controlSources, SourceMap testSources) { if (controlSources is null) { throw new ArgumentNullException(nameof(controlSources)); } if (testSources is null) { throw new ArgumentNullException(nameof(testSources)); } foreach (var control in controlSources.GetUnmatched()) { if (testSources.Contains(control.Attribute.Name) && testSources.IsUnmatched(control.Attribute.Name)) { yield return(new AttributeComparison(control, testSources[control.Attribute.Name])); } } yield break; }
private static IReadOnlyList <AttributeComparison> NoneAttributeMatcher( IDiffContext context, SourceMap controlAttributes, SourceMap testAttributes) => Array.Empty <AttributeComparison>();
private static IEnumerable <Comparison> OneToOneNodeListMatcher( IDiffContext context, SourceCollection controlNodes, SourceCollection testNodes) => OneToOneNodeMatcher.Match(context, controlNodes, testNodes);
private static IEnumerable <Comparison> NoneNodeMatcher(IDiffContext ctx, SourceCollection controlNodes, SourceCollection testNodes) => Array.Empty <Comparison>();