@@ -2448,3 +2448,224 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "Ensure no 'undefined' handler
24482448assert . ok ( ! jQuery . expr . attrHandle . hasOwnProperty ( "undefined" ) ,
24492449"Extra attr handlers are not added to Expr.attrHandle (https://github.com/jquery/sizzle/issues/353)" ) ;
24502450} ) ;
2451+
2452+ QUnit . test ( "jQuery.find.matchesSelector" , function ( assert ) {
2453+ assert . expect ( 15 ) ;
2454+
2455+ var link = document . getElementById ( "simon1" ) ,
2456+ input = document . getElementById ( "text1" ) ,
2457+ option = document . getElementById ( "option1a" ) ,
2458+ disconnected = document . createElement ( "div" ) ;
2459+
2460+ link . title = "Don't click me" ;
2461+ assert . ok ( jQuery . find . matchesSelector ( link , "[rel='bookmark']" ) , "attribute-equals string" ) ;
2462+ assert . ok ( jQuery . find . matchesSelector ( link , "[rel=bookmark]" ) , "attribute-equals identifier" ) ;
2463+ assert . ok ( jQuery . find . matchesSelector ( link , "[\nrel = bookmark\t]" ) ,
2464+ "attribute-equals identifier (whitespace ignored)" ) ;
2465+ assert . ok ( jQuery . find . matchesSelector ( link , "a[title=\"Don't click me\"]" ) ,
2466+ "attribute-equals string containing single quote" ) ;
2467+
2468+ // jQuery #12303
2469+ input . setAttribute ( "data-pos" , ":first" ) ;
2470+ assert . ok ( jQuery . find . matchesSelector ( input , "input[data-pos=\\:first]" ) ,
2471+ "attribute-equals POS in identifier" ) ;
2472+ assert . ok ( jQuery . find . matchesSelector ( input , "input[data-pos=':first']" ) ,
2473+ "attribute-equals POS in string" ) ;
2474+ assert . ok ( jQuery . find . matchesSelector ( input , ":input[data-pos=':first']" ) ,
2475+ "attribute-equals POS in string after pseudo" ) ;
2476+
2477+ option . setAttribute ( "test" , "" ) ;
2478+ assert . ok ( jQuery . find . matchesSelector ( option , "[id=option1a]" ) ,
2479+ "id attribute-equals identifier" ) ;
2480+ assert . ok ( jQuery . find . matchesSelector ( option , "[id*=option1][type!=checkbox]" ) ,
2481+ "attribute-not-equals identifier" ) ;
2482+ assert . ok ( jQuery . find . matchesSelector ( option , "[id*=option1]" ) , "attribute-contains identifier" ) ;
2483+ assert . ok ( ! jQuery . find . matchesSelector ( option , "[test^='']" ) ,
2484+ "attribute-starts-with empty string (negative)" ) ;
2485+
2486+ option . className = "=]" ;
2487+ assert . ok ( jQuery . find . matchesSelector ( option , ".\\=\\]" ) ,
2488+ "class selector with attribute-equals confusable" ) ;
2489+
2490+ assert . ok ( jQuery . find . matchesSelector ( disconnected , "div" ) , "disconnected element" ) ;
2491+ assert . ok ( jQuery . find . matchesSelector ( link , "* > *" ) , "child combinator matches in document" ) ;
2492+ assert . ok ( ! jQuery . find . matchesSelector ( disconnected , "* > *" ) , "child combinator fails in fragment" ) ;
2493+ } ) ;
2494+
2495+ QUnit . test ( "jQuery.find.matches" , function ( assert ) {
2496+ assert . expect ( 4 ) ;
2497+
2498+ var iframeChild ,
2499+ input = document . getElementById ( "text1" ) ,
2500+ div = document . createElement ( "div" ) ,
2501+ iframe = document . getElementById ( "iframe" ) ,
2502+ iframeDoc = iframe . contentDocument || iframe . contentWindow . document ;
2503+
2504+ assert . deepEqual ( jQuery . find . matches ( "input" , [ input ] ) , [ input ] ,
2505+ "jQuery.find.matches with seed of input element" ) ;
2506+ assert . deepEqual ( jQuery . find . matches ( "div" , [ div ] ) , [ div ] ,
2507+ "jQuery.find.matches with disconnected element" ) ;
2508+
2509+ iframeDoc . open ( ) ;
2510+ iframeDoc . write ( "<body><div id='foo'><div id='bar'></div></div></body>" ) ;
2511+ iframeDoc . close ( ) ;
2512+
2513+ iframeChild = iframeDoc . getElementById ( "bar" ) ;
2514+
2515+ assert . deepEqual (
2516+ jQuery . find . matches ( ":root > body > #foo > #bar" , [ iframeChild ] ) ,
2517+ [ iframeChild ] ,
2518+ "jQuery.find.matches infers context from element"
2519+ ) ;
2520+
2521+ assert . deepEqual (
2522+ jQuery . find . matches ( ":root *" , [ div , iframeChild , input ] ) ,
2523+ [ iframeChild , input ] ,
2524+ "jQuery.find.matches infers context from each seed element"
2525+ ) ;
2526+ } ) ;
2527+
2528+ QUnit . test ( "jQuery.find.select with pre-compiled function" , function ( assert ) {
2529+ assert . expect ( 6 ) ;
2530+
2531+ supportjQuery . each ( [
2532+ "#qunit-fixture #first" ,
2533+ "ol#listWithTabIndex > li[tabindex]" ,
2534+ "#liveSpan1"
2535+ ] , function ( i , selector ) {
2536+ var compiled = jQuery . find . compile ( selector ) ;
2537+ assert . equal ( jQuery . find . select ( compiled , document ) . length ,
2538+ 1 , "Should match using a compiled selector function" ) ;
2539+ assert . equal (
2540+ jQuery . find . select ( compiled , jQuery ( "#first" ) [ 0 ] ) . length ,
2541+ 0 , "Should not match with different context" ) ;
2542+ } ) ;
2543+ } ) ;
2544+
2545+ // Internal, but we test it for backwards compatibility for edge cases
2546+ QUnit . test ( "jQuery.find.tokenize" , function ( assert ) {
2547+ assert . expect ( 1 ) ;
2548+
2549+ var selector = "#id .class > div[prop=\"value\"] + input:nth-child(1):button, span:contains(\"Text\") ~ div:has(div:has(span)):not(.not-this.not-that > div)" ,
2550+ tokens = [
2551+ [
2552+ {
2553+ "value" :"#id" ,
2554+ "type" :"ID" ,
2555+ "matches" :[
2556+ "id"
2557+ ]
2558+ } ,
2559+ {
2560+ "value" :" " ,
2561+ "type" :" "
2562+ } ,
2563+ {
2564+ "value" :".class" ,
2565+ "type" :"CLASS" ,
2566+ "matches" :[
2567+ "class"
2568+ ]
2569+ } ,
2570+ {
2571+ "value" :" > " ,
2572+ "type" :">"
2573+ } ,
2574+ {
2575+ "value" :"div" ,
2576+ "type" :"TAG" ,
2577+ "matches" :[
2578+ "div"
2579+ ]
2580+ } ,
2581+ {
2582+ "value" :"[prop=\"value\"]" ,
2583+ "type" :"ATTR" ,
2584+ "matches" :[
2585+ "prop" ,
2586+ "=" ,
2587+ "value"
2588+ ]
2589+ } ,
2590+ {
2591+ "value" :" + " ,
2592+ "type" :"+"
2593+ } ,
2594+ {
2595+ "value" :"input" ,
2596+ "type" :"TAG" ,
2597+ "matches" :[
2598+ "input"
2599+ ]
2600+ } ,
2601+ {
2602+ "value" :":nth-child(1)" ,
2603+ "type" :"CHILD" ,
2604+ "matches" :[
2605+ "nth" ,
2606+ "child" ,
2607+ "1" ,
2608+ 0 ,
2609+ 1 ,
2610+ undefined ,
2611+ "" ,
2612+ "1"
2613+ ]
2614+ } ,
2615+ {
2616+ "value" :":button" ,
2617+ "type" :"PSEUDO" ,
2618+ "matches" :[
2619+ "button" ,
2620+ undefined
2621+ ]
2622+ }
2623+ ] ,
2624+ [
2625+ {
2626+ "value" :"span" ,
2627+ "type" :"TAG" ,
2628+ "matches" :[
2629+ "span"
2630+ ]
2631+ } ,
2632+ {
2633+ "value" :":contains(\"Text\")" ,
2634+ "type" :"PSEUDO" ,
2635+ "matches" :[
2636+ "contains" ,
2637+ "Text"
2638+ ]
2639+ } ,
2640+ {
2641+ "value" :" ~ " ,
2642+ "type" :"~"
2643+ } ,
2644+ {
2645+ "value" :"div" ,
2646+ "type" :"TAG" ,
2647+ "matches" :[
2648+ "div"
2649+ ]
2650+ } ,
2651+ {
2652+ "value" :":has(div:has(span))" ,
2653+ "type" :"PSEUDO" ,
2654+ "matches" :[
2655+ "has" ,
2656+ "div:has(span)"
2657+ ]
2658+ } ,
2659+ {
2660+ "value" :":not(.not-this.not-that > div)" ,
2661+ "type" :"PSEUDO" ,
2662+ "matches" :[
2663+ "not" ,
2664+ ".not-this.not-that > div"
2665+ ]
2666+ }
2667+ ]
2668+ ] ;
2669+
2670+ assert . deepEqual ( jQuery . find . tokenize ( selector ) , tokens , "Tokenization successful" ) ;
2671+ } ) ;