Subversion-Projekte lars-tiefland.zeldi.de_alt

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
2 lars 1
if ( window.sessionStorage ) {
2
	sessionStorage.clear();
3
}
4
jQuery.validator.defaults.debug = true;
5
$.mockjaxSettings.log = $.noop;
6
 
7
$.mockjax( {
8
	url: "form.php?user=Peter&password=foobar",
9
	responseText: "Hi Peter, welcome back.",
10
	responseStatus: 200,
11
	responseTime: 1
12
} );
13
 
14
$.mockjax( {
15
	url: "users.php",
16
	data: {
17
		username: /Peter2?|asdf/
18
	},
19
	responseText: "false",
20
	responseStatus: 200,
21
	responseTime: 1
22
} );
23
 
24
$.mockjax( {
25
	url: "users2.php",
26
	data: {
27
		username: "asdf"
28
	},
29
	responseText: "\"asdf is already taken, please try something else\"",
30
	responseStatus: 200,
31
	responseTime: 1
32
} );
33
 
34
$.mockjax( {
35
	url: "echo.php",
36
	response: function( data ) {
37
		this.responseText = JSON.stringify( data.data );
38
	},
39
	responseTime: 100
40
} );
41
 
42
$.mockjax( {
43
	url: "response.php",
44
	response: function( settings ) {
45
		var responseText = settings.data.responseText;
46
		if ( responseText ) {
47
			if ( typeof responseText === "function" ) {
48
				this.responseText = responseText();
49
			} else {
50
				this.responseText = responseText;
51
			}
52
		} else {
53
			this.responseText = "";
54
		}
55
		this.responseStatus = settings.data.responseStatus || 200;
56
		this.responseTime = settings.data.responseTime || 100;
57
	}
58
} );
59
 
60
$.mockjax( {
61
	url: "issue1508.php",
62
	response: function( settings ) {
63
		if ( /abc/i.test( settings.data.val2 ) ) {
64
			this.responseText = "false";
65
		} else {
66
			this.responseText = "true";
67
		}
68
	},
69
	responseStatus: 200,
70
	responseTime: 1
71
} );
72
 
73
$.mockjax( {
74
	url: "workemail.php",
75
	response: function( data ) {
76
		this.responseStatus = data.data.special === "somevalue" ? 200 : 400; //Requires special param for request
77
		if ( this.responseStatus === 200 ) { //Only if valid request - processing workemail
78
			this.responseText = JSON.stringify( data.data.email === "john.doe@company.com" );
79
		}
80
	}
81
} );
82
 
83
// Asserts that there is a visible error with the given text for the specified element
84
QUnit.assert.hasError = function( element, text, message ) {
85
	var errors = $( element ).closest( "form" ).validate().errorsFor( element[ 0 ] ),
86
		actual = ( errors.length === 1 && errors.is( ":visible" ) ) ? errors.text() : "";
87
	this.pushResult( {
88
		result: actual, actual: actual, expected: text, message: message
89
	} );
90
};
91
 
92
// Asserts that there is no visible error for the given element
93
QUnit.assert.noErrorFor = function( element, message ) {
94
	var errors = $( element ).closest( "form" ).validate().errorsFor( element[ 0 ] ),
95
		hidden = ( errors.length === 0 ) || ( errors.is( ":hidden" ) && ( errors.text() === "" ) );
96
	this.pushResult( {
97
		result: hidden, actual: hidden, expected: true, message: message
98
	} );
99
};
100
 
101
QUnit.module( "validator" );
102
 
103
QUnit.test( "Constructor", function( assert ) {
104
	var v1 = $( "#testForm1" ).validate(),
105
		v2 = $( "#testForm1" ).validate();
106
 
107
	assert.equal( v1, v2, "Calling validate() multiple times must return the same validator instance" );
108
	assert.equal( v1.elements().length, 3, "validator elements" );
109
} );
110
 
111
QUnit.test( "validate() without elements, with non-form elements", function( assert ) {
112
	assert.expect( 0 );
113
	$( "#doesntexist" ).validate();
114
} );
115
 
116
QUnit.test( "valid() plugin method", function( assert ) {
117
	var form = $( "#userForm" ),
118
		input = $( "#username" );
119
 
120
	form.validate();
121
	assert.ok( !form.valid(), "Form isn't valid yet" );
122
	assert.ok( !input.valid(), "Input isn't valid either" );
123
 
124
	input.val( "Hello world" );
125
	assert.ok( form.valid(), "Form is now valid" );
126
	assert.ok( input.valid(), "Input is valid, too" );
127
} );
128
 
129
QUnit.test( "valid() plugin method, multiple inputs", function( assert ) {
130
	var form = $( "#testForm1" ),
131
		validator = form.validate(),
132
		inputs = form.find( "input" );
133
 
134
	assert.ok( !inputs.valid(), "all invalid" );
135
	inputs.not( ":first" ).val( "ok" );
136
	assert.equal( validator.numberOfInvalids(), 2 );
137
	assert.strictEqual( inputs.valid(), false, "just one invalid" );
138
	inputs.val( "ok" );
139
	assert.strictEqual( inputs.valid(), true, "all valid" );
140
} );
141
 
142
QUnit.test( "valid() plugin method, special handling for checkable groups", function( assert ) {
143
 
144
	// Rule is defined on first checkbox, must apply to others, too
145
	var checkable = $( "#checkable2" );
146
	assert.ok( !checkable.valid(), "must be invalid, not checked yet" );
147
	checkable.attr( "checked", true );
148
	assert.ok( checkable.valid(), "valid, is now checked" );
149
	checkable.attr( "checked", false );
150
	assert.ok( !checkable.valid(), "invalid again" );
151
	$( "#checkable3" ).attr( "checked", true );
152
	assert.ok( checkable.valid(), "valid, third box is checked" );
153
} );
154
 
155
QUnit.test( "valid() ???", function( assert ) {
156
	assert.expect( 4 );
157
	var errorList = [
158
			{
159
				name: "meal",
160
				message: "foo",
161
				element: $( "#meal" )[ 0 ]
162
			}
163
		],
164
		v = $( "#testForm3" ).validate();
165
 
166
	assert.ok( v.valid(), "No errors, must be valid" );
167
	v.errorList = errorList;
168
	assert.ok( !v.valid(), "One error, must be invalid" );
169
	v.destroy();
170
	v = $( "#testForm3" ).validate();
171
	assert.ok( v.valid(), "No errors, must be valid and returning true" );
172
	v.errorList = errorList;
173
	assert.ok( !v.valid(), "One error, must be invalid" );
174
} );
175
 
176
QUnit.test( "valid(), ignores ignored elements", function( assert ) {
177
	$( "#testForm1clean" ).validate( {
178
		ignore: "#firstnamec",
179
		rules: {
180
			firstnamec: "required"
181
		}
182
	} );
183
	assert.ok( $( "#firstnamec" ).valid() );
184
} );
185
 
186
QUnit.test( "valid() should ignore elements that belong to other/nested forms", function( assert ) {
187
	var form = $( "#testForm28" );
188
 
189
	form.validate();
190
 
191
	// 1. Test with nested form
192
	form.append(
193
		"<form id='testForm28-nested'>" +
194
		"    <input type='text' name='f28nestedinput' required>" +
195
		"</form>"
196
	);
197
 
198
	try {
199
		form.valid();
200
		assert.ok( true, "It should ignore the input of nested form" );
201
	} catch ( err ) {
202
		assert.ok( false, "Shouldn't throw an error" );
203
	}
204
 
205
	// Remove the validator atteched to testForm28
206
	form.removeData( "validator" );
207
	$( "#testForm28-nested" ).remove();
208
 
209
	// 2. Test using another form outside of validated one
210
	form.parent().append(
211
		"<form id='testForm28-other'>" +
212
		"   <input type='text' name='f28otherinput' required>" +
213
		"   <input type='text' name='f28input' form='testForm28' required>" +
214
		"</form>"
215
	);
216
 
217
	$( "#testForm28-other" ).validate();
218
 
219
	try {
220
		$( "#testForm28-other" ).valid();
221
		assert.ok( true, "It should ignore the input of other form" );
222
	} catch ( err ) {
223
		assert.ok( false, "Shouldn't throw an error" );
224
	}
225
 
226
	$( "#testForm28-other" ).remove();
227
} );
228
 
229
QUnit.test( "form() should ignore elements that belong to other/nested forms", function( assert ) {
230
	var form = $( "#testForm28" );
231
	var v = form.validate();
232
 
233
	form.validate();
234
 
235
	// 1. Test with nested form
236
	form.append(
237
		"<form id='testForm28-nested'>" +
238
		"    <input type='text' name='f28nestedinput' required>" +
239
		"</form>"
240
	);
241
 
242
	try {
243
		v.form();
244
		assert.ok( true, "It should ignore the input of nested form" );
245
	} catch ( err ) {
246
		assert.ok( false, "Shouldn't throw an error" );
247
	}
248
 
249
	// Remove the validator atteched to testForm28
250
	form.removeData( "validator" );
251
	$( "#testForm28-nested" ).remove();
252
 
253
	// 2. Test using another form outside of validated one
254
	form.parent().append(
255
		"<form id='testForm28-other'>" +
256
		"   <input type='text' name='f28otherinput' required>" +
257
		"   <input type='text' name='f28input' form='testForm28' required>" +
258
		"</form>"
259
	);
260
 
261
	v = $( "#testForm28-other" ).validate();
262
 
263
	try {
264
		v.form();
265
		assert.ok( true, "It should ignore the input of other form" );
266
	} catch ( err ) {
267
		assert.ok( false, "Shouldn't throw an error" );
268
	}
269
 
270
	$( "#testForm28-other" ).remove();
271
} );
272
 
273
QUnit.test( "elements() should ignore elements that belong to other/nested forms", function( assert ) {
274
	var form = $( "#testForm28" );
275
	var v = form.validate();
276
 
277
	// 1. Test with nested form
278
	form.append(
279
		"<form id='testForm28-nested'>" +
280
		"    <input type='text' name='f28nestedinput' required>" +
281
		"</form>"
282
	);
283
 
284
	try {
285
		assert.equal( v.elements().length, 1, "There should be only one element to validate" );
286
	} catch ( err ) {
287
		assert.ok( false, "Shouldn't throw an error" );
288
	}
289
 
290
	// Remove the validator atteched to testForm28
291
	form.removeData( "validator" );
292
	$( "#testForm28-nested" ).remove();
293
 
294
	// 2. Test using another form outside of validated one
295
	form.parent().append(
296
		"<form id='testForm28-other'>" +
297
		"   <input type='text' name='f28otherinput' required>" +
298
		"   <input type='text' name='f28input' form='testForm28' required>" +
299
		"</form>"
300
	);
301
 
302
	v = $( "#testForm28-other" ).validate();
303
 
304
	try {
305
		assert.equal( v.elements().length, 1, "There should be only one element to validate" );
306
	} catch ( err ) {
307
		assert.ok( false, "Shouldn't throw an error" );
308
	}
309
 
310
	$( "#testForm28-other" ).remove();
311
} );
312
 
313
QUnit.test( "Ignore elements that have form attribute set to other forms", function( assert ) {
314
 
315
	// Append a form that contains an input with form attribute set to "testForm28"
316
	$( "#testForm28" ).parent().append(
317
		"<form id='testForm28-other'>" +
318
		"   <input type='text' name='f28otherinput' required>" +
319
		"   <input type='text' name='f28input' form='testForm28' required>" +
320
		"</form>"
321
	);
322
 
323
	// Attach the plugin to the appended form
324
	$( "#testForm28-other" ).validate();
325
 
326
	// 1. Simulate typing
327
	try {
328
		$( "[name='f28input']", "#testForm28-other" ).trigger( "keyup" );
329
		assert.ok( true, "It should ignore the input of other form" );
330
	} catch ( err ) {
331
		assert.ok( false, "Shouldn't throw an error while typing" );
332
	}
333
 
334
	// 2. Simulate forcussing in the input
335
	try {
336
		$( "[name='f28input']", "#testForm28-other" ).trigger( "focusin" );
337
		assert.ok( true, "It should ignore the input of other form" );
338
	} catch ( err ) {
339
		assert.ok( false, "Shouldn't throw an error on focus" );
340
	}
341
 
342
	// 3. Simulate focussing out the input
343
	try {
344
		$( "[name='f28input']", "#testForm28-other" ).trigger( "focusout" );
345
		assert.ok( true, "It should ignore the input of other form" );
346
	} catch ( err ) {
347
		assert.ok( false, "Shouldn't throw an error on blur" );
348
	}
349
 
350
	$( "#testForm28-other" ).remove();
351
} );
352
 
353
QUnit.test( "addMethod", function( assert ) {
354
	assert.expect( 3 );
355
	$.validator.addMethod( "hi", function( value ) {
356
		return value === "hi";
357
	}, "hi me too" );
358
	var method = $.validator.methods.hi,
359
		e = $( "#text1" )[ 0 ];
360
	assert.ok( !method( e.value, e ), "Invalid" );
361
	e.value = "hi";
362
	assert.ok( method( e.value, e ), "Invalid" );
363
	assert.ok( jQuery.validator.messages.hi === "hi me too", "Check custom message" );
364
} );
365
 
366
QUnit.test( "addMethod2", function( assert ) {
367
	assert.expect( 4 );
368
	$.validator.addMethod( "complicatedPassword", function( value, element ) {
369
		return this.optional( element ) || /\D/.test( value ) && /\d/.test( value );
370
	}, "Your password must contain at least one number and one letter" );
371
	var v = jQuery( "#form" ).validate( {
372
			rules: {
373
				action: { complicatedPassword: true }
374
			}
375
		} ),
376
		e = $( "#text1" )[ 0 ];
377
 
378
	e.value = "";
379
	assert.strictEqual( v.element( e ), true, "Rule is optional, valid" );
380
	assert.equal( v.size(), 0 );
381
	e.value = "ko";
382
	assert.ok( !v.element( e ), "Invalid, doesn't contain one of the required characters" );
383
	e.value = "ko1";
384
	assert.ok( v.element( e ) );
385
} );
386
 
387
QUnit.test( "form(): simple", function( assert ) {
388
	assert.expect( 2 );
389
	var form = $( "#testForm1" )[ 0 ],
390
		v = $( form ).validate();
391
 
392
	assert.ok( !v.form(), "Invalid form" );
393
	$( "#firstname" ).val( "hi" );
394
	$( "#lastname" ).val( "hi" );
395
	assert.ok( v.form(), "Valid form" );
396
} );
397
 
398
QUnit.test( "form(): checkboxes: min/required", function( assert ) {
399
	assert.expect( 3 );
400
	var form = $( "#testForm6" )[ 0 ],
401
		v = $( form ).validate();
402
 
403
	assert.ok( !v.form(), "Invalid form" );
404
	$( "#form6check1" ).attr( "checked", true );
405
	assert.ok( !v.form(), "Invalid form" );
406
	$( "#form6check2" ).attr( "checked", true );
407
	assert.ok( v.form(), "Valid form" );
408
} );
409
 
410
QUnit.test( "form(): radio buttons: required", function( assert ) {
411
	assert.expect( 6 );
412
	var form = $( "#testForm10" )[ 0 ],
413
		v = $( form ).validate( {
414
			rules: {
415
				testForm10Radio: "required"
416
			}
417
		} );
418
 
419
	assert.ok( !v.form(), "Invalid Form" );
420
	assert.equal( $( "#testForm10Radio1" ).attr( "class" ), "error" );
421
	assert.equal( $( "#testForm10Radio2" ).attr( "class" ), "error" );
422
 
423
	$( "#testForm10Radio2" ).attr( "checked", true );
424
	assert.ok( v.form(), "Valid form" );
425
 
426
	assert.equal( $( "#testForm10Radio1" ).attr( "class" ), "valid" );
427
	assert.equal( $( "#testForm10Radio2" ).attr( "class" ), "valid" );
428
} );
429
 
430
QUnit.test( "form(): selects: min/required", function( assert ) {
431
	assert.expect( 3 );
432
	var form = $( "#testForm7" )[ 0 ],
433
		v = $( form ).validate();
434
 
435
	assert.ok( !v.form(), "Invalid form" );
436
	$( "#optionxa" ).attr( "selected", true );
437
	assert.ok( !v.form(), "Invalid form" );
438
	$( "#optionxb" ).attr( "selected", true );
439
	assert.ok( v.form(), "Valid form" );
440
} );
441
 
442
QUnit.test( "form(): with equalTo", function( assert ) {
443
	assert.expect( 2 );
444
	var form = $( "#testForm5" )[ 0 ],
445
		v = $( form ).validate();
446
 
447
	assert.ok( !v.form(), "Invalid form" );
448
	$( "#x1, #x2" ).val( "hi" );
449
	assert.ok( v.form(), "Valid form" );
450
} );
451
 
452
QUnit.test( "form(): with equalTo and onfocusout=false", function( assert ) {
453
	assert.expect( 4 );
454
	var form = $( "#testForm5" )[ 0 ],
455
		v = $( form ).validate( {
456
			onfocusout: false,
457
			showErrors: function() {
458
				assert.ok( true, "showErrors should only be called twice" );
459
				this.defaultShowErrors();
460
			}
461
		} );
462
 
463
	$( "#x1, #x2" ).val( "hi" );
464
	assert.ok( v.form(), "Valid form" );
465
	$( "#x2" ).val( "not equal" ).blur();
466
	assert.ok( !v.form(), "Invalid form" );
467
} );
468
 
469
QUnit.test( "check(): simple", function( assert ) {
470
	assert.expect( 3 );
471
	var element = $( "#firstname" )[ 0 ],
472
		v = $( "#testForm1" ).validate();
473
 
474
	assert.ok( v.size() === 0, "No errors yet" );
475
	v.check( element );
476
	assert.ok( v.size() === 1, "error exists" );
477
	v.errorList = [];
478
	$( "#firstname" ).val( "hi" );
479
	v.check( element );
480
	assert.ok( v.size() === 0, "No more errors" );
481
} );
482
 
483
QUnit.test( "numberOfInvalids(): count invalid fields with empty message", function( assert ) {
484
	assert.expect( 2 );
485
 
486
	var v = $( "#testForm23" ).validate( {
487
		rules: {
488
			box1: {
489
				required: true
490
			},
491
			box2: {
492
				required: true
493
			}
494
		}
495
	} );
496
 
497
	var requiredMsg = $.validator.messages.required;
498
	$.validator.messages.required = "";
499
 
500
	v.form();
501
 
502
	assert.equal( v.errorList.length, 2, "The form has two errors" );
503
	assert.equal( v.numberOfInvalids(), 2, "The form has two errors" );
504
 
505
	$.validator.messages.required = requiredMsg;
506
} );
507
 
508
QUnit.test( "hide(): input", function( assert ) {
509
	assert.expect( 3 );
510
	var errorLabel = $( "#errorFirstname" ),
511
		element = $( "#firstname" )[ 0 ],
512
		v;
513
 
514
	element.value = "bla";
515
	v = $( "#testForm1" ).validate();
516
	errorLabel.show();
517
 
518
	assert.ok( errorLabel.is( ":visible" ), "Error label visible before validation" );
519
	assert.ok( v.element( element ) );
520
	assert.ok( errorLabel.is( ":hidden" ), "Error label not visible after validation" );
521
} );
522
 
523
QUnit.test( "hide(): radio", function( assert ) {
524
	assert.expect( 2 );
525
	var errorLabel = $( "#agreeLabel" ),
526
		element = $( "#agb" )[ 0 ],
527
		v;
528
 
529
	element.checked = true;
530
	v = $( "#testForm2" ).validate( { errorClass: "xerror" } );
531
	errorLabel.show();
532
 
533
	assert.ok( errorLabel.is( ":visible" ), "Error label visible after validation" );
534
	v.element( element );
535
	assert.ok( errorLabel.is( ":hidden" ), "Error label not visible after hiding it" );
536
} );
537
 
538
QUnit.test( "hide(): errorWrapper", function( assert ) {
539
	assert.expect( 2 );
540
	var errorLabel = $( "#errorWrapper" ),
541
		element = $( "#meal" )[ 0 ],
542
		v;
543
 
544
	element.selectedIndex = 1;
545
	errorLabel.show();
546
 
547
	assert.ok( errorLabel.is( ":visible" ), "Error label visible after validation" );
548
	v = $( "#testForm3" ).validate( { wrapper: "li", errorLabelContainer: $( "#errorContainer" ) } );
549
	v.element( element );
550
	assert.ok( errorLabel.is( ":hidden" ), "Error label not visible after hiding it" );
551
} );
552
 
553
QUnit.test( "hide(): container", function( assert ) {
554
	assert.expect( 4 );
555
	var errorLabel = $( "#errorContainer" ),
556
		v = $( "#testForm3" ).validate( { errorWrapper: "li", errorContainer: $( "#errorContainer" ) } );
557
 
558
	v.form();
559
	assert.ok( errorLabel.is( ":visible" ), "Error label visible after validation" );
560
	$( "#meal" )[ 0 ].selectedIndex = 1;
561
	v.form();
562
	assert.ok( errorLabel.is( ":hidden" ), "Error label not visible after hiding it" );
563
	$( "#meal" )[ 0 ].selectedIndex = -1;
564
	v.element( "#meal" );
565
	assert.ok( errorLabel.is( ":visible" ), "Error label visible after validation" );
566
	$( "#meal" )[ 0 ].selectedIndex = 1;
567
	v.element( "#meal" );
568
	assert.ok( errorLabel.is( ":hidden" ), "Error label not visible after hiding it" );
569
} );
570
 
571
QUnit.test( "submitHandler keeps submitting button", function( assert ) {
572
	var button, event;
573
 
574
	$( "#userForm" ).validate( {
575
		debug: false,
576
		submitHandler: function( form ) {
577
 
578
			var hidden = $( form ).find( "input:hidden" )[ 0 ];
579
			assert.deepEqual( hidden.value, button.value );
580
			assert.deepEqual( hidden.name, button.name );
581
 
582
			return false;
583
		}
584
	} );
585
	$( "#username" ).val( "bla" );
586
	button = $( "#userForm :submit" )[ 0 ];
587
	event = $.Event( "click" );
588
	event.preventDefault();
589
	$.event.trigger( event, null, button );
590
	$( "#userForm" ).submit();
591
} );
592
 
593
QUnit.test( "submitHandler keeps submitting button, even if descendants are clicked", function( assert ) {
594
	var button = $( "#testForm27 :submit" )[ 0 ];
595
	var v = $( "#testForm27" ).validate( {
596
		debug: false,
597
		submitHandler: function( form ) {
598
 
599
			// Compare the button with the `submitButton` property
600
			assert.deepEqual(
601
				v.submitButton, button, "The submitButton property should be the same as button"
602
			);
603
 
604
			var hidden = $( form ).find( "input:hidden" )[ 0 ];
605
			assert.deepEqual( hidden.value, button.value );
606
			assert.deepEqual( hidden.name, button.name );
607
 
608
			return false;
609
		}
610
	} );
611
 
612
	$( "#testForm27 [name=\"year\"]" ).val( "2016" );
613
 
614
	$( button ).find( "span" ).click();
615
} );
616
 
617
QUnit.test( "handle() should ensure the value of the used submit button is passed on for scripted submit triggered by stopRequest()", function( assert ) {
618
	var $form = $( "#userForm" );
619
	var button = $( ":submit", $form )[ 0 ];
620
	var done = assert.async();
621
	var v = $form.validate( {
622
		debug: true,
623
		rules: {
624
			username: {
625
				remote: {
626
					url: "issue1508.php"
627
				}
628
			}
629
		}
630
	} );
631
	var i = 1;
632
 
633
	// Register a `submit` event after the one registred by this plugin
634
	$form.on( "submit", function() {
635
 
636
		// Ignoring the first submit that was triggered manually by clicking
637
		// the submit button. The first submit will be aborted by this plugin
638
		// in order to wait for `remote` method to finish validating the input
639
		if ( i > 0 ) {
640
			i--;
641
			return false;
642
		}
643
 
644
		// The second submit is the one triggered by `stopRequest()` after the
645
		// `remote` method has finished processing its attached input.
646
 
647
		// Compare the button with the `submitButton` property
648
		assert.deepEqual(
649
			v.submitButton, button, "The submitButton property should be the same as button"
650
		);
651
 
652
		var hidden = $form.find( "input:hidden" )[ 0 ];
653
		assert.deepEqual( hidden.value, button.value );
654
		assert.deepEqual( hidden.name, button.name );
655
 
656
		done();
657
 
658
		return false;
659
	} );
660
 
661
	$( "input[name='username']", $form ).val( "something" );
662
 
663
	// Submit the form
664
	$( button ).click();
665
} );
666
 
667
QUnit.test( "validation triggered on radio/checkbox when using keyboard", function( assert ) {
668
    assert.expect( 1 );
669
	var input, i, events, triggeredEvents = 0,
670
		done = assert.async();
671
 
672
	$( "#form" ).validate( {
673
		onfocusin: function() {
674
			triggeredEvents++;
675
		},
676
		onfocusout: function() {
677
			triggeredEvents++;
678
		},
679
		onkeyup: function() {
680
			triggeredEvents++;
681
		}
682
	} );
683
 
684
	events = [
685
		$.Event( "focusin" ),
686
		$.Event( "focusout" ),
687
		$.Event( "keyup" )
688
	];
689
 
690
	input = $( "#form :radio:first" );
691
	for ( i = 0; i < events.length; i++ ) {
692
		input.trigger( events[ i ] );
693
	}
694
 
695
	input = $( "#form :checkbox:first" );
696
	for ( i = 0; i < events.length; i++ ) {
697
		input.trigger( events[ i ] );
698
	}
699
 
700
	setTimeout( function() {
701
 
702
		// Assert all event handlers fired
703
		assert.equal( triggeredEvents, 6 );
704
		done();
705
	} );
706
} );
707
 
708
QUnit.test( "validation triggered on button", function( assert ) {
709
	assert.expect( 1 );
710
	var input, i, events, triggeredEvents = 0,
711
		done = assert.async();
712
 
713
	$( "#form" ).validate( {
714
		onfocusin: function() {
715
			triggeredEvents++;
716
		},
717
		onfocusout: function() {
718
			triggeredEvents++;
719
		},
720
		onkeyup: function() {
721
			triggeredEvents++;
722
		}
723
	} );
724
 
725
	events = [
726
		$.Event( "focusin" ),
727
		$.Event( "focusout" ),
728
		$.Event( "keyup" )
729
	];
730
 
731
	input = $( "#form :button" );
732
	for ( i = 0; i < events.length; i++ ) {
733
		input.trigger( events[ i ] );
734
	}
735
 
736
	setTimeout( function() {
737
 
738
		// Assert all event handlers fired
739
		assert.equal( triggeredEvents, 6 );
740
		done();
741
	} );
742
} );
743
 
744
QUnit.test( "validation triggered on radio/checkbox when using mouseclick", function( assert ) {
745
    assert.expect( 1 );
746
	var input, i, events, triggeredEvents = 0,
747
		done = assert.async();
748
 
749
	$( "#form" ).validate( {
750
		onclick: function() {
751
			triggeredEvents++;
752
		}
753
	} );
754
 
755
	events = [
756
		$.Event( "click" )
757
	];
758
 
759
	input = $( "#form :radio:first" );
760
	for ( i = 0; i < events.length; i++ ) {
761
		input.trigger( events[ i ] );
762
	}
763
 
764
	input = $( "#form :checkbox:first" );
765
	for ( i = 0; i < events.length; i++ ) {
766
		input.trigger( events[ i ] );
767
	}
768
 
769
	setTimeout( function() {
770
 
771
		// Assert all event handlers fired
772
		assert.equal( triggeredEvents, 2 );
773
		done();
774
	} );
775
} );
776
 
777
QUnit.test( "showErrors()", function( assert ) {
778
	assert.expect( 4 );
779
	var errorLabel = $( "#errorFirstname" ).hide(),
780
		v = $( "#testForm1" ).validate();
781
 
782
	assert.ok( errorLabel.is( ":hidden" ) );
783
	assert.equal( $( "#lastname" ).next( ".error:not(input)" ).length, 0 );
784
	v.showErrors( { "firstname": "required", "lastname": "bla" } );
785
	assert.equal( errorLabel.is( ":visible" ), true );
786
	assert.equal( $( "#lastname" ).next( ".error:not(input)" ).is( ":visible" ), true );
787
} );
788
 
789
QUnit.test( "showErrors(), allow empty string and null as default message", function( assert ) {
790
	$( "#userForm" ).validate( {
791
		rules: {
792
			username: {
793
				required: true,
794
				minlength: 3
795
			}
796
		},
797
		messages: {
798
			username: {
799
				required: "",
800
				minlength: "too short"
801
			}
802
		}
803
	} );
804
	assert.ok( !$( "#username" ).valid() );
805
	assert.equal( $( "#username" ).next( ".error:not(input)" ).text(), "" );
806
 
807
	$( "#username" ).val( "ab" );
808
	assert.ok( !$( "#username" ).valid() );
809
	assert.equal( $( "#username" ).next( ".error:not(input)" ).text(), "too short" );
810
 
811
	$( "#username" ).val( "abc" );
812
	assert.ok( $( "#username" ).valid() );
813
	assert.ok( $( "#username" ).next( ".error:not(input)" ).is( ":hidden" ) );
814
} );
815
 
816
QUnit.test( "showErrors() - external messages", function( assert ) {
817
	assert.expect( 4 );
818
	var methods = $.extend( {}, $.validator.methods ),
819
		messages = $.extend( {}, $.validator.messages ),
820
		form, v;
821
 
822
	$.validator.addMethod( "foo", function() { return false; } );
823
	$.validator.addMethod( "bar", function() { return false; } );
824
	assert.equal( $( "#testForm4 #f1" ).next( ".error:not(input)" ).length, 0 );
825
	assert.equal( $( "#testForm4 #f2" ).next( ".error:not(input)" ).length, 0 );
826
 
827
	form = $( "#testForm4" )[ 0 ];
828
	v = $( form ).validate( {
829
		messages: {
830
			f1: "Please!",
831
			f2: "Wohoo!"
832
		}
833
	} );
834
	v.form();
835
	assert.equal( $( "#testForm4 #f1" ).next( ".error:not(input)" ).text(), "Please!" );
836
	assert.equal( $( "#testForm4 #f2" ).next( ".error:not(input)" ).text(), "Wohoo!" );
837
 
838
	$.validator.methods = methods;
839
	$.validator.messages = messages;
840
} );
841
 
842
QUnit.test( "showErrors() - custom handler", function( assert ) {
843
	assert.expect( 5 );
844
	var v = $( "#testForm1" ).validate( {
845
		showErrors: function( errorMap, errorList ) {
846
			assert.equal( v, this );
847
			assert.equal( v.errorList, errorList );
848
			assert.equal( v.errorMap, errorMap );
849
			assert.equal( errorMap.firstname, "buga" );
850
			assert.equal( errorMap.lastname, "buga" );
851
		}
852
	} );
853
	v.form();
854
} );
855
 
856
QUnit.test( "option: (un)highlight, default", function( assert ) {
857
	$( "#testForm1" ).validate();
858
	var e = $( "#firstname" );
859
	assert.ok( !e.hasClass( "error" ) );
860
	assert.ok( !e.hasClass( "valid" ) );
861
	e.valid();
862
	assert.ok( e.hasClass( "error" ) );
863
	assert.ok( !e.hasClass( "valid" ) );
864
	e.val( "hithere" ).valid();
865
	assert.ok( !e.hasClass( "error" ) );
866
	assert.ok( e.hasClass( "valid" ) );
867
} );
868
 
869
QUnit.test( "option: (un)highlight, nothing", function( assert ) {
870
	assert.expect( 3 );
871
	$( "#testForm1" ).validate( {
872
		highlight: false,
873
		unhighlight: false
874
	} );
875
	var e = $( "#firstname" );
876
	assert.ok( !e.hasClass( "error" ) );
877
	e.valid();
878
	assert.ok( !e.hasClass( "error" ) );
879
	e.valid();
880
	assert.ok( !e.hasClass( "error" ) );
881
} );
882
 
883
QUnit.test( "option: (un)highlight, custom", function( assert ) {
884
	assert.expect( 5 );
885
	$( "#testForm1clean" ).validate( {
886
		highlight: function( element, errorClass ) {
887
			assert.equal( errorClass, "invalid" );
888
			$( element ).hide();
889
		},
890
		unhighlight: function( element, errorClass ) {
891
			assert.equal( errorClass, "invalid" );
892
			$( element ).show();
893
		},
894
		ignore: "",
895
		errorClass: "invalid",
896
		rules: {
897
			firstnamec: "required"
898
		}
899
	} );
900
	var e = $( "#firstnamec" );
901
	assert.ok( e.is( ":visible" ) );
902
	e.valid();
903
	assert.ok( !e.is( ":visible" ) );
904
	e.val( "hithere" ).valid();
905
	assert.ok( e.is( ":visible" ) );
906
} );
907
 
908
QUnit.test( "option: (un)highlight, custom2", function( assert ) {
909
	assert.expect( 6 );
910
	var e, l;
911
	$( "#testForm1" ).validate( {
912
		highlight: function( element, errorClass ) {
913
			$( element ).addClass( errorClass );
914
			$( element ).next( ".error:not(input)" ).addClass( errorClass );
915
		},
916
		unhighlight: function( element, errorClass ) {
917
			$( element ).removeClass( errorClass );
918
			$( element ).next( ".error:not(input)" ).removeClass( errorClass );
919
		},
920
		errorClass: "invalid"
921
	} );
922
 
923
	e = $( "#firstname" );
924
	l = $( "#errorFirstname" );
925
 
926
	assert.ok( !e.is( ".invalid" ) );
927
	assert.ok( !l.is( ".invalid" ) );
928
	e.valid();
929
	assert.ok( e.is( ".invalid" ) );
930
	assert.ok( l.is( ".invalid" ) );
931
	e.val( "hithere" ).valid();
932
	assert.ok( !e.is( ".invalid" ) );
933
	assert.ok( !l.is( ".invalid" ) );
934
} );
935
 
936
QUnit.test( "option: errorPlacement", function( assert ) {
937
	assert.expect( 1 );
938
	var v = $( "#testForm1" ).validate( {
939
		errorPlacement: function() {
940
			assert.strictEqual( this, v, "'this' inside errorPlacement should be the plugin instance" );
941
		}
942
	} );
943
 
944
	v.form();
945
} );
946
 
947
QUnit.test( "option: focusCleanup default false", function( assert ) {
948
	var form = $( "#userForm" );
949
	form.validate();
950
	form.valid();
951
	assert.ok( form.find( "#username" ).next( ".error:not(input)" ).is( ":visible" ) );
952
	$( "#username" ).focus();
953
	assert.ok( form.find( "#username" ).next( ".error:not(input)" ).is( ":visible" ) );
954
} );
955
 
956
QUnit.test( "option: focusCleanup true", function( assert ) {
957
	var form = $( "#userForm" );
958
	form.validate( {
959
		focusCleanup: true
960
	} );
961
	form.valid();
962
	assert.ok( form.find( "#username" ).next( ".error:not(input)" ).is( ":visible" ) );
963
	$( "#username" ).focus().trigger( "focusin" );
964
	assert.ok( !form.find( "#username" ).next( ".error:not(input)" ).is( ":visible" ) );
965
} );
966
 
967
QUnit.test( "option: focusCleanup with wrapper", function( assert ) {
968
	var form = $( "#userForm" );
969
	form.validate( {
970
		focusCleanup: true,
971
		wrapper: "span"
972
	} );
973
	form.valid();
974
	assert.ok( form.is( ":has(span:visible:has(.error#username-error))" ) );
975
	$( "#username" ).focus().trigger( "focusin" );
976
	assert.ok( !form.is( ":has(span:visible:has(.error#username-error))" ) );
977
} );
978
 
979
QUnit.test( "option: errorClass with multiple classes", function( assert ) {
980
	var form = $( "#userForm" );
981
	form.validate( {
982
		focusCleanup: true,
983
		wrapper: "span",
984
		errorClass: "error error1 error2"
985
	} );
986
	form.valid();
987
	assert.ok( form.is( ":has(span:visible:has(.error#username-error))" ) );
988
	assert.ok( form.is( ":has(span:visible:has(.error1#username-error))" ) );
989
	assert.ok( form.is( ":has(span:visible:has(.error2#username-error))" ) );
990
	$( "#username" ).focus().trigger( "focusin" );
991
	assert.ok( !form.is( ":has(span:visible:has(.error#username-error))" ) );
992
	assert.ok( !form.is( ":has(span:visible:has(.error1#username-error))" ) );
993
	assert.ok( !form.is( ":has(span:visible:has(.error2#username-error))" ) );
994
} );
995
 
996
QUnit.test( "defaultMessage(), empty title is ignored", function( assert ) {
997
	var v = $( "#userForm" ).validate();
998
	assert.equal( v.defaultMessage( $( "#username" )[ 0 ], { method: "required", parameters: true } ), "This field is required." );
999
 
1000
	// Using the old way when we pass the name of a method as the second parameters.
1001
	assert.equal( v.defaultMessage( $( "#username" )[ 0 ], "required" ), "This field is required." );
1002
} );
1003
 
1004
QUnit.test( "previousValue()", function( assert ) {
1005
	assert.expect( 2 );
1006
 
1007
	var e = $( "#username" ),
1008
		v = $( "#userForm" ).validate(),
1009
		expectedRemote = {
1010
			old: null,
1011
			valid: true,
1012
			message: "Please fix this field."
1013
		}, expectedRequired = {
1014
			old: null,
1015
			valid: true,
1016
			message: "This field is required."
1017
		};
1018
 
1019
	assert.deepEqual( v.previousValue( e[ 0 ] ), expectedRemote, "should be the same" );
1020
 
1021
	e.removeData( "previousValue" );
1022
	assert.deepEqual( v.previousValue( e[ 0 ], "required" ), expectedRequired, "should be the same" );
1023
} );
1024
 
1025
QUnit.test( "#741: move message processing from formatAndAdd to defaultMessage", function( assert ) {
1026
	var v = $( "#testForm22" ).validate();
1027
	assert.equal( v.defaultMessage( $( "#tF22Input" )[ 0 ], { method: "minlength", parameters: 5 } ),
1028
		"You should enter at least 5 characters.", "defaultMessage() now format the messages" );
1029
 
1030
	$( "#tF22Input" ).val( "abc" );
1031
	v.form();
1032
	assert.equal( v.errorList[ 0 ].message, "You should enter at least 5 characters." );
1033
} );
1034
 
1035
QUnit.test( "formatAndAdd", function( assert ) {
1036
	assert.expect( 4 );
1037
	var v = $( "#form" ).validate(),
1038
		fakeElement = { form: $( "#form" )[ 0 ], name: "bar" };
1039
 
1040
	v.formatAndAdd( fakeElement, { method: "maxlength", parameters: 2 } );
1041
	assert.equal( v.errorList[ 0 ].message, "Please enter no more than 2 characters." );
1042
	assert.equal( v.errorList[ 0 ].element.name, "bar" );
1043
 
1044
	v.formatAndAdd( fakeElement, { method: "range", parameters: [ 2, 4 ] } );
1045
	assert.equal( v.errorList[ 1 ].message, "Please enter a value between 2 and 4." );
1046
 
1047
	v.formatAndAdd( fakeElement, { method: "range", parameters: [ 0, 4 ] } );
1048
	assert.equal( v.errorList[ 2 ].message, "Please enter a value between 0 and 4." );
1049
} );
1050
 
1051
QUnit.test( "formatAndAdd2", function( assert ) {
1052
	assert.expect( 3 );
1053
	var v = $( "#form" ).validate(),
1054
		fakeElement = { form: $( "#form" )[ 0 ], name: "bar" };
1055
 
1056
	jQuery.validator.messages.test1 = function( param, element ) {
1057
		assert.equal( this, v );
1058
		assert.equal( param, 0 );
1059
		return "element " + element.name + " is not valid";
1060
	};
1061
	v.formatAndAdd( fakeElement, { method: "test1", parameters: 0 } );
1062
	assert.equal( v.errorList[ 0 ].message, "element bar is not valid" );
1063
} );
1064
 
1065
QUnit.test( "formatAndAdd, auto detect substitution string", function( assert ) {
1066
	var v = $( "#testForm1clean" ).validate( {
1067
		rules: {
1068
			firstnamec: {
1069
				required: true,
1070
				rangelength: [ 5, 10 ]
1071
			}
1072
		},
1073
		messages: {
1074
			firstnamec: {
1075
				rangelength: "at least ${0}, up to {1}"
1076
			}
1077
		}
1078
	} );
1079
	$( "#firstnamec" ).val( "abc" );
1080
	v.form();
1081
	assert.equal( v.errorList[ 0 ].message, "at least 5, up to 10" );
1082
} );
1083
 
1084
QUnit.test( "option invalidHandler", function( assert ) {
1085
	assert.expect( 1 );
1086
	var done = assert.async();
1087
	$( "#testForm1clean" ).validate( {
1088
		invalidHandler: function() {
1089
			assert.ok( true, "invalid-form event triggered called" );
1090
			done();
1091
		}
1092
	} );
1093
	$( "#usernamec" ).val( "asdf" ).rules( "add", { required: true, minlength: 5 } );
1094
	$( "#testForm1clean" ).submit();
1095
} );
1096
 
1097
QUnit.test( "findByName()", function( assert ) {
1098
	assert.deepEqual(
1099
		new $.validator( {}, document.getElementById( "form" ) )
1100
			.findByName( document.getElementById( "radio1" ).name )
1101
			.get(),
1102
		$( "#form" ).find( "[name=radio1]" ).get()
1103
	);
1104
} );
1105
 
1106
QUnit.test( "focusInvalid()", function( assert ) {
1107
 
1108
	// TODO when using custom focusin, this is triggered just once
1109
	// TODO when using 1.4 focusin, triggered twice; fix once not testing against 1.3 anymore
1110
	// assert.expect( 1 );
1111
	var inputs = $( "#testForm1 input" ).focus( function() {
1112
			assert.equal( this, inputs[ 0 ], "focused first element" );
1113
		} ),
1114
		v = $( "#testForm1" ).validate();
1115
 
1116
	v.form();
1117
	v.focusInvalid();
1118
} );
1119
 
1120
QUnit.test( "focusInvalid() after validate a custom set of inputs", function( assert ) {
1121
	var form = $( "#testForm1" ),
1122
		validator = form.validate(),
1123
 
1124
		// It's important the order of Valid, Invalid, Valid so last active element it's a valid element before focus
1125
		inputs = $( "#firstname, #lastname, #something" );
1126
 
1127
	$( "#firstname" ).val( "ok" );
1128
 
1129
	assert.ok( !inputs.valid(), "just one invalid" );
1130
 
1131
	validator.focusInvalid();
1132
 
1133
	assert.equal( form[ 0 ].ownerDocument.activeElement, $( "#lastname" )[ 0 ], "focused first element" );
1134
} );
1135
 
1136
QUnit.test( "findLastActive()", function( assert ) {
1137
	assert.expect( 3 );
1138
	var v = $( "#testForm1" ).validate(),
1139
		lastActive;
1140
 
1141
	assert.ok( !v.findLastActive() );
1142
	v.form();
1143
	v.focusInvalid();
1144
	assert.equal( v.findLastActive(), $( "#firstname" )[ 0 ] );
1145
	lastActive = $( "#lastname" ).trigger( "focus" ).trigger( "focusin" )[ 0 ];
1146
 
1147
	assert.equal( v.lastActive, lastActive );
1148
} );
1149
 
1150
QUnit.test( "elementValue() finds radios/checkboxes only within the current form", function( assert ) {
1151
	assert.expect( 1 );
1152
	var v = $( "#userForm" ).validate(), foreignRadio = $( "#radio2" )[ 0 ];
1153
 
1154
	assert.ok( !v.elementValue( foreignRadio ) );
1155
} );
1156
 
1157
QUnit.test( "elementValue() returns the file input's name without the prefix 'C:\\fakepath\\' ", function( assert ) {
1158
	var v = $( "#userForm" ).validate(),
1159
 
1160
		// A fake file input
1161
		fileInput = {
1162
			name: "fakeFile",
1163
			type: "file",
1164
			files: {},
1165
			nodeName: "INPUT",
1166
			value: "C:\\fakepath\\somefile.txt",
1167
			form: $( "#userForm" )[ 0 ],
1168
			hasAttribute: function() { return false; },
1169
			getAttribute: function( name ) {
1170
				if ( name === "type" ) {
1171
					return "file";
1172
				}
1173
 
1174
				return undefined;
1175
			},
1176
			setAttribute: function() {}
1177
		};
1178
 
1179
	v.defaultShowErrors = function() {};
1180
	v.validationTargetFor = function() {
1181
		return fileInput;
1182
	};
1183
 
1184
	assert.equal( v.elementValue( fileInput ), "somefile.txt" );
1185
 
1186
	$( fileInput ).rules( "add", {
1187
		minlength: 10
1188
	} );
1189
 
1190
	assert.ok( v.element( fileInput ), "The fake file input is valid (length = 12, minlength = 10)" );
1191
 
1192
	fileInput.value = "C:\\fakepath\\file.txt";
1193
	assert.ok( !v.element( fileInput ), "The fake file input is invalid (length = 8, minlength = 10)" );
1194
 
1195
	$( fileInput ).rules( "remove" );
1196
	$( fileInput ).rules( "add", {
1197
		maxlength: 10
1198
	} );
1199
 
1200
	assert.ok( v.element( fileInput ), "The fake file input is valid (length = 8, maxlength = 10)" );
1201
 
1202
	fileInput.value = "C:\\fakepath\\fakefile.txt";
1203
	assert.ok( !v.element( fileInput ), "The fake file input is invalid (length = 12, maxlength = 10)" );
1204
} );
1205
 
1206
QUnit.test( "Required rule should not take precedence over number & digits rules", function( assert ) {
1207
	var v = $( "#userForm" ).validate(),
1208
 
1209
		// A fake number input
1210
		numberInput = {
1211
			name: "fakeNumber",
1212
			type: "number",
1213
			nodeName: "INPUT",
1214
			value: "",
1215
			form: $( "#userForm" )[ 0 ],
1216
			validity: {
1217
				badInput: false
1218
			},
1219
			hasAttribute: function() { return false; },
1220
			getAttribute: function( name ) {
1221
				return this[ name ];
1222
			},
1223
			setAttribute: function() {}
1224
		};
1225
 
1226
	v.defaultShowErrors = function() {};
1227
	v.validationTargetFor = function() {
1228
		return numberInput;
1229
	};
1230
 
1231
	$( numberInput ).rules( "add", {
1232
		required: true
1233
	} );
1234
 
1235
	assert.deepEqual( $( numberInput ).rules(), { required: true, number: true } );
1236
	assert.ok( !v.element( numberInput ), "The fake number input is invalid" );
1237
	assert.equal( v.errorList[ 0 ].message, $.validator.messages.required, "The error message should be the one of required rule." );
1238
 
1239
	numberInput.value = "Not A Number";
1240
	numberInput.validity.badInput = true;
1241
	assert.ok( !v.element( numberInput ), "The fake number input is invalid" );
1242
	assert.equal( v.errorList[ 0 ].message, $.validator.messages.number, "The error message should be the one of number rule." );
1243
 
1244
	numberInput.value = "2015";
1245
	numberInput.validity.badInput = false;
1246
	assert.ok( v.element( numberInput ), "The fake number input is valid" );
1247
} );
1248
 
1249
QUnit.test( "validating multiple checkboxes with 'required'", function( assert ) {
1250
	assert.expect( 3 );
1251
	var checkboxes = $( "#form input[name=check3]" ).prop( "checked", false ),
1252
		v;
1253
	assert.equal( checkboxes.length, 5 );
1254
 
1255
	v = $( "#form" ).validate( {
1256
		rules: {
1257
			check3: "required"
1258
		}
1259
	} );
1260
	v.form();
1261
 
1262
	assert.equal( v.size(), 1 );
1263
	checkboxes.filter( ":last" ).prop( "checked", true );
1264
	v.form();
1265
	assert.equal( v.size(), 0 );
1266
} );
1267
 
1268
QUnit.test( "dynamic form", function( assert ) {
1269
	var counter = 0,
1270
		v;
1271
	function add() {
1272
		$( "<input data-rule-required='true' name='list" + counter++ + "' />" ).appendTo( "#testForm2" );
1273
	}
1274
	function errors( expected, message ) {
1275
		assert.equal( v.size(), expected, message );
1276
	}
1277
 
1278
	v = $( "#testForm2" ).validate();
1279
	v.form();
1280
	errors( 1 );
1281
	add();
1282
	v.form();
1283
	errors( 2 );
1284
	add();
1285
	v.form();
1286
	errors( 3 );
1287
	$( "#testForm2 input[name=list1]" ).remove();
1288
	v.form();
1289
	errors( 2 );
1290
	add();
1291
	v.form();
1292
	errors( 3 );
1293
	$( "#testForm2 input[name^=list]" ).remove();
1294
	v.form();
1295
	errors( 1 );
1296
	$( "#agb" ).attr( "disabled", true );
1297
	v.form();
1298
	errors( 0 );
1299
	$( "#agb" ).attr( "disabled", false );
1300
	v.form();
1301
	errors( 1 );
1302
} );
1303
 
1304
QUnit.test( "idOrName()", function( assert ) {
1305
	assert.expect( 4 );
1306
	var v = $( "#testForm1" ).validate();
1307
	assert.equal( v.idOrName( $( "#form8input" )[ 0 ] ), "form8input" );
1308
	assert.equal( v.idOrName( $( "#form6check1" )[ 0 ] ), "check" );
1309
	assert.equal( v.idOrName( $( "#agb" )[ 0 ] ), "agree" );
1310
	assert.equal( v.idOrName( $( "#form :button" )[ 0 ] ), "button" );
1311
} );
1312
 
1313
QUnit.test( "resetForm()", function( assert ) {
1314
	function errors( expected, message ) {
1315
		assert.equal( v.size(), expected, message );
1316
	}
1317
	var v = $( "#testForm1" ).validate();
1318
	v.form();
1319
	errors( 2 );
1320
	assert.ok( $( "#firstname" ).hasClass( "error" ) );
1321
	assert.ok( $( "#something" ).hasClass( "valid" ) );
1322
	$( "#firstname" ).val( "hiy" );
1323
	v.resetForm();
1324
	errors( 0 );
1325
	assert.ok( !$( "#firstname" ).hasClass( "error" ) );
1326
	assert.ok( !$( "#something" ).hasClass( "valid" ) );
1327
	assert.equal( $( "#firstname" ).val(), "", "form plugin is included, therefor resetForm must also reset inputs, not only errors" );
1328
} );
1329
 
1330
QUnit.test( "resetForm() clean styles when custom highlight function is used", function( assert ) {
1331
	var form = $( "#testForm1clean" ),
1332
		e = $( "#firstnamec" );
1333
	form.validate( {
1334
		highlight: function( element ) {
1335
			$( element ).hide();
1336
		},
1337
		unhighlight: function( element ) {
1338
			$( element ).show();
1339
		},
1340
		ignore: "",
1341
		errorClass: "invalid",
1342
		rules: {
1343
			firstnamec: "required"
1344
		}
1345
	} );
1346
	e.valid();
1347
	assert.ok( !e.is( ":visible" ) );
1348
	form.validate().resetForm();
1349
	assert.ok( e.is( ":visible" ) );
1350
} );
1351
 
1352
QUnit.test( "message from title", function( assert ) {
1353
	var v = $( "#withTitle" ).validate();
1354
	v.checkForm();
1355
	assert.equal( v.errorList[ 0 ].message, "fromtitle", "title not used" );
1356
} );
1357
 
1358
QUnit.test( "ignoreTitle", function( assert ) {
1359
	var v = $( "#withTitle" ).validate( { ignoreTitle: true } );
1360
	v.checkForm();
1361
	assert.equal( v.errorList[ 0 ].message, $.validator.messages.required, "title used when it should have been ignored" );
1362
} );
1363
 
1364
QUnit.test( "ajaxSubmit", function( assert ) {
1365
	assert.expect( 1 );
1366
	var done = assert.async();
1367
	$( "#user" ).val( "Peter" );
1368
	$( "#password" ).val( "foobar" );
1369
	jQuery( "#signupForm" ).validate( {
1370
		debug: false,
1371
		submitHandler: function( form ) {
1372
			jQuery( form ).ajaxSubmit( {
1373
				success: function( response ) {
1374
					assert.equal( response, "Hi Peter, welcome back." );
1375
					done();
1376
				}
1377
			} );
1378
 
1379
			return false;
1380
		}
1381
	} );
1382
	jQuery( "#signupForm" ).triggerHandler( "submit" );
1383
} );
1384
 
1385
QUnit.test( "validating groups settings parameter", function( assert ) {
1386
	var form = $( "<form>" ),
1387
		validate = form.validate( {
1388
			groups: {
1389
				arrayGroup: [ "input one", "input-two", "input three" ],
1390
				stringGroup: "input-four input-five input-six"
1391
			}
1392
		} );
1393
 
1394
	assert.equal( validate.groups[ "input one" ], "arrayGroup" );
1395
	assert.equal( validate.groups[ "input-two" ], "arrayGroup" );
1396
	assert.equal( validate.groups[ "input three" ], "arrayGroup" );
1397
	assert.equal( validate.groups[ "input-four" ], "stringGroup" );
1398
	assert.equal( validate.groups[ "input-five" ], "stringGroup" );
1399
	assert.equal( validate.groups[ "input-six" ], "stringGroup" );
1400
} );
1401
 
1402
QUnit.test( "validating group of elements", function( assert ) {
1403
	var form  = $( "#testForm26" ),
1404
		day   = form.find( "[name='day']" ),
1405
		month = form.find( "[name='month']" ),
1406
		year  = form.find( "[name='year']" ),
1407
		event = $.Event( "keyup", { keyCode: 9 } ),
1408
		v = form.validate( {
1409
			groups: {
1410
				mydate: "day month year"
1411
			}
1412
		} ),
1413
		invalidEls;
1414
 
1415
	v.form();
1416
 
1417
	assert.equal( v.invalidElements().length, 3, "All 3 elements are invalid" );
1418
 
1419
	// Tab to `month`
1420
	day.blur();
1421
	month.trigger( event );
1422
	month.focus();
1423
 
1424
	month.val( 2 );
1425
 
1426
	// Trigger validation via click event
1427
	month.trigger( "click" );
1428
 
1429
	invalidEls = v.invalidElements();
1430
 
1431
	assert.equal( invalidEls.length, 2, "Only 2 elements are invalid" );
1432
	assert.deepEqual( invalidEls[ 0 ], day[ 0 ], "The day element is invalid" );
1433
	assert.deepEqual( invalidEls[ 1 ], year[ 0 ], "The year element is invalid" );
1434
} );
1435
 
1436
QUnit.test( "bypassing validation on form submission", function( assert ) {
1437
	var form = $( "#bypassValidation" ),
1438
		normalSubmission = $( "form#bypassValidation :input[id=normalSubmit]" ),
1439
		bypassSubmitWithCancel = $( "form#bypassValidation :input[id=bypassSubmitWithCancel]" ),
1440
		bypassSubmitWithNoValidate1 = $( "form#bypassValidation :input[id=bypassSubmitWithNoValidate1]" ),
1441
		bypassSubmitWithNoValidate2 = $( "form#bypassValidation :input[id=bypassSubmitWithNoValidate2]" ),
1442
		$v = form.validate( {
1443
			debug: true
1444
		} );
1445
 
1446
	bypassSubmitWithCancel.click();
1447
	assert.equal( $v.numberOfInvalids(), 0, "Validation was bypassed using CSS 'cancel' class." );
1448
	$v.resetForm();
1449
 
1450
	bypassSubmitWithNoValidate1.click();
1451
	assert.equal( $v.numberOfInvalids(), 0, "Validation was bypassed using blank 'formnovalidate' attribute." );
1452
	$v.resetForm();
1453
 
1454
	bypassSubmitWithNoValidate2.click();
1455
	assert.equal( $v.numberOfInvalids(), 0, "Validation was bypassed using 'formnovalidate=\"formnovalidate\"' attribute." );
1456
	$v.resetForm();
1457
 
1458
	normalSubmission.click();
1459
	assert.equal( $v.numberOfInvalids(), 1, "Validation failed correctly" );
1460
} );
1461
 
1462
QUnit.test( "works on contenteditable fields", function( assert ) {
1463
	var form = $( "#contenteditableForm" );
1464
	form.valid();
1465
	assert.hasError( $( "#contenteditableNumberInvalid" ), "Please enter a valid number." );
1466
	assert.hasError( $( "#contenteditableRequiredInvalid" ), "This field is required." );
1467
	assert.hasError( $( "#contenteditableInput" ), "Please enter a valid number." );
1468
	assert.noErrorFor( $( "#contenteditableNumberValid" ) );
1469
	assert.noErrorFor( $( "#contenteditableRequiredValid" ) );
1470
} );
1471
 
1472
QUnit.test( "works on contenteditable fields on input event", function( assert ) {
1473
	$( "#contenteditableForm" ).validate();
1474
 
1475
	$( "#contenteditableNumberInvalid" ).focus();
1476
	$( "#contenteditableRequiredInvalid" ).focus();
1477
	$( "#contenteditableInput" ).keyup();
1478
	$( "#contenteditableNumberValid" ).focus();
1479
	$( "#contenteditableRequiredValid" ).keyup();
1480
 
1481
	assert.hasError( $( "#contenteditableNumberInvalid" ), "Please enter a valid number." );
1482
	assert.noErrorFor( $( "#contenteditableNumberValid" ) );
1483
	assert.noErrorFor( $( "#contenteditableRequiredValid" ) );
1484
} );
1485
 
1486
QUnit.test( "Assign rules to contenteditable via .validate() method", function( assert ) {
1487
	assert.expect( 2 );
1488
	var form = $( "#_contenteditableForm" );
1489
	var v = form.validate( {
1490
		rules: {
1491
			first_name: {
1492
				required: true
1493
			},
1494
			something: {
1495
				required: true
1496
			}
1497
		}
1498
	} );
1499
	var firstNameRules = $( "#first_name", form ).rules();
1500
	var expectedRules = { required: true };
1501
 
1502
	assert.deepEqual(
1503
		firstNameRules, expectedRules, "The rules should be the same"
1504
	);
1505
 
1506
	v.form();
1507
 
1508
	assert.equal( v.numberOfInvalids(), 2, "The form has two errors" );
1509
} );
1510
 
1511
QUnit.test( "Assign rules to contenteditable via .rules() method", function( assert ) {
1512
	assert.expect( 2 );
1513
	var form = $( "#_contenteditableForm" );
1514
	var v = form.validate( {
1515
		rules: {
1516
			something: {
1517
				required: true
1518
			}
1519
		}
1520
	} );
1521
 
1522
	$( "#first_name", form ).rules( "add", {
1523
		required: true
1524
	} );
1525
 
1526
	var firstNameRules = $( "#first_name", form ).rules();
1527
	var expectedRules = { required: true };
1528
 
1529
	assert.deepEqual(
1530
		firstNameRules, expectedRules, "The rules should be the same"
1531
	);
1532
 
1533
	v.form();
1534
 
1535
	assert.equal( v.numberOfInvalids(), 2, "The form has two errors" );
1536
} );
1537
 
1538
QUnit.module( "misc" );
1539
 
1540
QUnit.test( "success option", function( assert ) {
1541
	assert.expect( 7 );
1542
	assert.equal( $( "#firstname" ).val(), "" );
1543
	var v = $( "#testForm1" ).validate( {
1544
			success: "valid"
1545
		} ),
1546
		label = $( "#testForm1 .error:not(input)" );
1547
 
1548
	assert.ok( label.is( ".error" ) );
1549
	assert.ok( !label.is( ".valid" ) );
1550
	v.form();
1551
	assert.ok( label.is( ".error" ) );
1552
	assert.ok( !label.is( ".valid" ) );
1553
	$( "#firstname" ).val( "hi" );
1554
	v.form();
1555
	assert.ok( label.is( ".error" ) );
1556
	assert.ok( label.is( ".valid" ) );
1557
} );
1558
 
1559
QUnit.test( "success option2", function( assert ) {
1560
	assert.expect( 5 );
1561
	assert.equal( $( "#firstname" ).val(), "" );
1562
	var v = $( "#testForm1" ).validate( {
1563
			success: "valid"
1564
		} ),
1565
		label = $( "#testForm1 .error:not(input)" );
1566
 
1567
	assert.ok( label.is( ".error" ) );
1568
	assert.ok( !label.is( ".valid" ) );
1569
	$( "#firstname" ).val( "hi" );
1570
	v.form();
1571
	assert.ok( label.is( ".error" ) );
1572
	assert.ok( label.is( ".valid" ) );
1573
} );
1574
 
1575
QUnit.test( "success option3", function( assert ) {
1576
	assert.expect( 5 );
1577
	assert.equal( $( "#firstname" ).val(), "" );
1578
	$( "#errorFirstname" ).remove();
1579
	var v = $( "#testForm1" ).validate( {
1580
			success: "valid"
1581
		} ),
1582
		labels;
1583
 
1584
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1585
	$( "#firstname" ).val( "hi" );
1586
	v.form();
1587
	labels = $( "#testForm1 .error:not(input)" );
1588
 
1589
	assert.equal( labels.length, 3 );
1590
	assert.ok( labels.eq( 0 ).is( ".valid" ) );
1591
	assert.ok( !labels.eq( 1 ).is( ".valid" ) );
1592
} );
1593
 
1594
QUnit.test( "successlist", function( assert ) {
1595
	var v = $( "#form" ).validate( { success: "xyz" } );
1596
	v.form();
1597
	assert.equal( v.successList.length, 0 );
1598
} );
1599
 
1600
QUnit.test( "success isn't called for optional elements with no other rules", function( assert ) {
1601
	assert.expect( 4 );
1602
	assert.equal( $( "#firstname" ).removeAttr( "data-rule-required" ).removeAttr( "data-rule-minlength" ).val(), "" );
1603
	$( "#something" ).remove();
1604
	$( "#lastname" ).remove();
1605
	$( "#errorFirstname" ).remove();
1606
	var v = $( "#testForm1" ).validate( {
1607
		success: function() {
1608
			assert.ok( false, "don't call success for optional elements!" );
1609
		},
1610
		rules: {
1611
			firstname: { required: false }
1612
		}
1613
	} );
1614
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1615
	v.form();
1616
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1617
	$( "#firstname" ).valid();
1618
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1619
} );
1620
 
1621
QUnit.test( "success is called for optional elements with other rules", function( assert ) {
1622
	assert.expect( 1 );
1623
 
1624
	$.validator.addMethod( "custom1", function() {
1625
		return true;
1626
	}, "" );
1627
 
1628
	$( "#testForm1clean" ).validate( {
1629
		success: function() {
1630
			assert.ok( true, "success called correctly!" );
1631
		},
1632
		rules: {
1633
			firstnamec: {
1634
				required: false,
1635
				custom1: true
1636
			}
1637
		}
1638
	} );
1639
 
1640
	$( "#firstnamec" ).valid();
1641
 
1642
	delete $.validator.methods.custom1;
1643
} );
1644
 
1645
QUnit.test( "success callback with element", function( assert ) {
1646
	assert.expect( 1 );
1647
	var v = $( "#userForm" ).validate( {
1648
		success: function( label, element ) {
1649
			assert.equal( element, $( "#username" ).get( 0 ) );
1650
		}
1651
	} );
1652
	$( "#username" ).val( "hi" );
1653
	v.form();
1654
} );
1655
 
1656
QUnit.test( "all rules are evaluated even if one returns a dependency-mistmatch", function( assert ) {
1657
	assert.expect( 6 );
1658
	assert.equal( $( "#firstname" ).removeAttr( "data-rule-required" ).removeAttr( "data-rule-minlength" ).val(), "" );
1659
	$( "#lastname" ).remove();
1660
	$( "#errorFirstname" ).remove();
1661
	$.validator.addMethod( "custom1", function() {
1662
		assert.ok( true, "custom method must be evaluated" );
1663
		return true;
1664
	}, "" );
1665
	var v = $( "#testForm1" ).validate( {
1666
		rules: {
1667
			firstname: {
1668
				email: true,
1669
				custom1: true
1670
			}
1671
		}
1672
	} );
1673
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1674
	v.form();
1675
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1676
	$( "#firstname" ).valid();
1677
	assert.equal( $( "#testForm1 .error:not(input)" ).length, 0 );
1678
 
1679
	delete $.validator.methods.custom1;
1680
	delete $.validator.messages.custom1;
1681
} );
1682
 
1683
QUnit.test( "messages", function( assert ) {
1684
	var m = jQuery.validator.messages;
1685
	assert.equal( m.maxlength( 0 ), "Please enter no more than 0 characters." );
1686
	assert.equal( m.minlength( 1 ), "Please enter at least 1 characters." );
1687
	assert.equal( m.rangelength( [ 1, 2 ] ), "Please enter a value between 1 and 2 characters long." );
1688
	assert.equal( m.max( 1 ), "Please enter a value less than or equal to 1." );
1689
	assert.equal( m.min( 0 ), "Please enter a value greater than or equal to 0." );
1690
	assert.equal( m.range( [ 1, 2 ] ), "Please enter a value between 1 and 2." );
1691
	assert.equal( m.step( 2 ), "Please enter a multiple of 2." );
1692
} );
1693
 
1694
QUnit.test( "jQuery.validator.format", function( assert ) {
1695
	assert.equal(
1696
		jQuery.validator.format( "Please enter a value between {0} and {1}.", 0, 1 ),
1697
		"Please enter a value between 0 and 1."
1698
	);
1699
	assert.equal(
1700
		jQuery.validator.format( "{0} is too fast! Enter a value smaller then {0} and at least {1}", 0, -15 ),
1701
		"0 is too fast! Enter a value smaller then 0 and at least -15"
1702
	);
1703
	var template = jQuery.validator.format( "{0} is too fast! Enter a value smaller then {0} and at least {1}" );
1704
	assert.equal( template( 0, -15 ), "0 is too fast! Enter a value smaller then 0 and at least -15" );
1705
	template = jQuery.validator.format( "Please enter a value between {0} and {1}." );
1706
	assert.equal( template( [ 1, 2 ] ), "Please enter a value between 1 and 2." );
1707
	assert.equal( $.validator.format( "{0}", "$0" ), "$0" );
1708
} );
1709
 
1710
QUnit.test( "option: ignore", function( assert ) {
1711
	var v = $( "#testForm1" ).validate( {
1712
		ignore: "[name=lastname]"
1713
	} );
1714
	v.form();
1715
	assert.equal( v.size(), 1 );
1716
} );
1717
 
1718
QUnit.test( "option: subformRequired", function( assert ) {
1719
	jQuery.validator.addMethod( "billingRequired", function( value, element ) {
1720
		if ( $( "#bill_to_co" ).is( ":checked" ) ) {
1721
			return $( element ).parents( "#subform" ).length;
1722
		}
1723
		return !this.optional( element );
1724
	}, "" );
1725
	var v = $( "#subformRequired" ).validate();
1726
	v.form();
1727
	assert.equal( v.size(), 1 );
1728
	$( "#bill_to_co" ).attr( "checked", false );
1729
	v.form();
1730
	assert.equal( v.size(), 2 );
1731
 
1732
	delete $.validator.methods.billingRequired;
1733
	delete $.validator.messages.billingRequired;
1734
} );
1735
 
1736
QUnit.module( "expressions" );
1737
 
1738
QUnit.test( "expression: :blank", function( assert ) {
1739
	var e = $( "#lastname" )[ 0 ];
1740
	assert.equal( $( e ).filter( ":blank" ).length, 1 );
1741
	e.value = " ";
1742
	assert.equal( $( e ).filter( ":blank" ).length, 1 );
1743
	e.value = "   ";
1744
	assert.equal( $( e ).filter( ":blank" ).length, 1 );
1745
	e.value = " a ";
1746
	assert.equal( $( e ).filter( ":blank" ).length, 0 );
1747
} );
1748
 
1749
QUnit.test( "expression: :filled", function( assert ) {
1750
	var e = $( "#lastname" )[ 0 ];
1751
	assert.equal( $( e ).filter( ":filled" ).length, 0 );
1752
	e.value = " ";
1753
	assert.equal( $( e ).filter( ":filled" ).length, 0 );
1754
	e.value = "   ";
1755
	assert.equal( $( e ).filter( ":filled" ).length, 0 );
1756
	e.value = " a ";
1757
	assert.equal( $( e ).filter( ":filled" ).length, 1 );
1758
  e = $( "#meal" )[ 0 ];
1759
  assert.equal( $( e ).filter( ":filled" ).length, 0 );
1760
	$( e ).val( "1" );
1761
	assert.equal( $( e ).filter( ":filled" ).length, 1 );
1762
  e = $( "#selectf7" )[ 0 ];
1763
  assert.equal( $( e ).filter( ":filled" ).length, 0 );
1764
	$( e ).val( [ "1", "2" ] );
1765
	assert.equal( $( e ).filter( ":filled" ).length, 1 );
1766
} );
1767
 
1768
QUnit.test( "expression: :unchecked", function( assert ) {
1769
	var e = $( "#check2" )[ 0 ];
1770
	assert.equal( $( e ).filter( ":unchecked" ).length, 1 );
1771
	e.checked = true;
1772
	assert.equal( $( e ).filter( ":unchecked" ).length, 0 );
1773
	e.checked = false;
1774
	assert.equal( $( e ).filter( ":unchecked" ).length, 1 );
1775
} );
1776
 
1777
QUnit.module( "events" );
1778
 
1779
QUnit.test( "validate on blur", function( assert ) {
1780
	function errors( expected, message ) {
1781
		assert.equal( v.size(), expected, message );
1782
	}
1783
	function labels( expected ) {
1784
		assert.equal( v.errors().filter( ":visible" ).length, expected );
1785
	}
1786
	function blur( target ) {
1787
		target.trigger( "blur" ).trigger( "focusout" );
1788
	}
1789
	$( "#errorFirstname" ).hide();
1790
	var e = $( "#firstname" ),
1791
		v = $( "#testForm1" ).validate();
1792
 
1793
	$( "#something" ).val( "" );
1794
	blur( e );
1795
	errors( 0, "No value yet, required is skipped on blur" );
1796
	labels( 0 );
1797
	e.val( "h" );
1798
	blur( e );
1799
	errors( 1, "Required was ignored, but as something was entered, check other rules, minlength isn't met" );
1800
	labels( 1 );
1801
	e.val( "hh" );
1802
	blur( e );
1803
	errors( 0, "All is fine" );
1804
	labels( 0 );
1805
	e.val( "" );
1806
	v.form();
1807
	errors( 3, "Submit checks all rules, both fields invalid" );
1808
	labels( 3 );
1809
	blur( e );
1810
	errors( 1, "Blurring the field results in emptying the error list first, then checking the invalid field: its still invalid, don't remove the error" );
1811
	labels( 3 );
1812
	e.val( "h" );
1813
	blur( e );
1814
	errors( 1, "Entering a single character fulfills required, but not minlength: 2, still invalid" );
1815
	labels( 3 );
1816
	e.val( "hh" );
1817
	blur( e );
1818
	errors( 0, "Both required and minlength are met, no errors left" );
1819
	labels( 2 );
1820
} );
1821
 
1822
QUnit.test( "validate on keyup", function( assert ) {
1823
	function errors( expected, message ) {
1824
		assert.equal( v.size(), expected, message );
1825
	}
1826
	function keyup( target ) {
1827
		target.trigger( "keyup" );
1828
	}
1829
	var e = $( "#firstname" ),
1830
		v = $( "#testForm1" ).validate();
1831
 
1832
	keyup( e );
1833
	errors( 0, "No value, no errors" );
1834
	e.val( "a" );
1835
	keyup( e );
1836
	errors( 0, "Value, but not invalid" );
1837
	e.val( "" );
1838
	v.form();
1839
	errors( 2, "Both invalid" );
1840
	keyup( e );
1841
	errors( 1, "Only one field validated, still invalid" );
1842
	e.val( "hh" );
1843
	keyup( e );
1844
	errors( 0, "Not invalid anymore" );
1845
	e.val( "h" );
1846
	keyup( e );
1847
	errors( 1, "Field didn't loose focus, so validate again, invalid" );
1848
	e.val( "hh" );
1849
	keyup( e );
1850
	errors( 0, "Valid" );
1851
} );
1852
 
1853
QUnit.test( "validate on not keyup, only blur", function( assert ) {
1854
	function errors( expected, message ) {
1855
		assert.equal( v.size(), expected, message );
1856
	}
1857
	var e = $( "#firstname" ),
1858
		v = $( "#testForm1" ).validate( {
1859
			onkeyup: false
1860
		} );
1861
 
1862
	errors( 0 );
1863
	e.val( "a" );
1864
	e.trigger( "keyup" );
1865
	e.keyup();
1866
	errors( 0 );
1867
	e.trigger( "blur" ).trigger( "focusout" );
1868
	errors( 1 );
1869
} );
1870
 
1871
QUnit.test( "validate on keyup and blur", function( assert ) {
1872
	function errors( expected, message ) {
1873
		assert.equal( v.size(), expected, message );
1874
	}
1875
	var e = $( "#firstname" ),
1876
		v = $( "#testForm1" ).validate();
1877
 
1878
	errors( 0 );
1879
	e.val( "a" );
1880
	e.trigger( "keyup" );
1881
	errors( 0 );
1882
	e.trigger( "blur" ).trigger( "focusout" );
1883
	errors( 1 );
1884
} );
1885
 
1886
QUnit.test( "validate email on keyup and blur", function( assert ) {
1887
	function errors( expected, message ) {
1888
		assert.equal( v.size(), expected, message );
1889
	}
1890
	var e = $( "#firstname" ),
1891
		v = $( "#testForm1" ).validate();
1892
 
1893
	v.form();
1894
	errors( 2 );
1895
	e.val( "a" );
1896
	e.trigger( "keyup" );
1897
	errors( 1 );
1898
	e.val( "aa" );
1899
	e.trigger( "keyup" );
1900
	errors( 0 );
1901
} );
1902
 
1903
QUnit.test( "don't revalidate the field when pressing special characters", function( assert ) {
1904
	function errors( expected, message ) {
1905
		assert.equal( v.size(), expected, message );
1906
	}
1907
 
1908
	function triggerEvent( element, keycode ) {
1909
		var event = $.Event( "keyup", { keyCode: keycode } );
1910
		element.trigger( event );
1911
	}
1912
 
1913
	var e = $( "#firstname" ),
1914
		v = $( "#testForm1" ).validate(),
1915
		excludedKeys = {
1916
			"Shift": 16,
1917
			"Ctrl": 17,
1918
			"Alt": 18,
1919
			"Caps lock": 20,
1920
			"End": 35,
1921
			"Home": 36,
1922
			"Left arrow": 37,
1923
			"Up arrow": 38,
1924
			"Right arrow": 39,
1925
			"Down arrow": 40,
1926
			"Insert": 45,
1927
			"Num lock": 144,
1928
			"Alt GR": 225
1929
		};
1930
 
1931
	// To make sure there is only one error, that one of #firstname field
1932
	$( "#firstname" ).val( "" );
1933
	$( "#lastname" ).val( "something" );
1934
	$( "#something" ).val( "something" );
1935
 
1936
	// Validate the form
1937
	v.form();
1938
	errors( 1, "Validate manually" );
1939
 
1940
	// Check for special keys
1941
	e.val( "aaa" );
1942
	$.each( excludedKeys, function( key, keyCode ) {
1943
		triggerEvent( e, keyCode );
1944
		errors( 1, key + " key" );
1945
	} );
1946
 
1947
	// Normal keyup
1948
	e.val( "aaaaa" );
1949
	e.trigger( "keyup" );
1950
	errors( 0, "Normal keyup" );
1951
} );
1952
 
1953
QUnit.test( "#1508: Validation fails to trigger when next field is already filled out", function( assert ) {
1954
 
1955
	// The next field is already filled out.
1956
	$( "#box2" ).val( "something" );
1957
 
1958
	var event   = $.Event( "keyup", { keyCode: 9 } ),
1959
		element = $( "#box1" ),
1960
		nextE   = $( "#box2" ),
1961
		validator = $( "#testForm23" ).validate( {
1962
			rules: {
1963
				box1: {
1964
					required: true
1965
				},
1966
				box2: {
1967
					required: true
1968
				}
1969
			}
1970
		} ),
1971
		check = function( value ) {
1972
 
1973
			// Fill the first element
1974
			element.val( "something" );
1975
 
1976
			// Tab to the next field
1977
			element.blur();
1978
			nextE.trigger( event );
1979
			nextE.focus();
1980
 
1981
			// Tab back to element
1982
			nextE.blur();
1983
			element.trigger( event );
1984
			element.focus();
1985
 
1986
			// Change the content
1987
			element.val( value );
1988
			element.trigger( "keyup" );
1989
		},
1990
		eq = function( expected, msg ) {
1991
			assert.equal( validator.numberOfInvalids(), expected, "There is only one invalid element." );
1992
			assert.equal( validator.invalidElements()[ 0 ], element[ 0 ], msg );
1993
		};
1994
 
1995
	check( "" );
1996
	eq( 1, "The box1 element should be invalid" );
1997
} );
1998
 
1999
QUnit.test( "[Remote rule] #1508: Validation fails to trigger when next field is already filled out", function( assert ) {
2000
	assert.expect( 2 );
2001
 
2002
	// The next field is already filled out.
2003
	$( "#val3" ).val( "something" );
2004
 
2005
	var event   = $.Event( "keyup", { keyCode: 9 } ),
2006
		element = $( "#val2" ),
2007
		nextE   = $( "#val3" ),
2008
		done = assert.async(),
2009
		validator = $( "#testForm24" ).validate( {
2010
			rules: {
2011
				val2: {
2012
					remote: {
2013
						url: "issue1508.php"
2014
					}
2015
				},
2016
				val3: {
2017
					required: true
2018
				}
2019
			}
2020
		} ),
2021
		check = function( value ) {
2022
 
2023
			// Fill the first element
2024
			element.val( "something" );
2025
 
2026
			// Tab to the next field
2027
			element.blur();
2028
			nextE.trigger( event );
2029
			nextE.focus();
2030
 
2031
			// Make sure all events will be called before the bellow code
2032
			setTimeout( function() {
2033
 
2034
				// Tab back to element
2035
				nextE.blur();
2036
				element.trigger( event );
2037
				element.focus();
2038
 
2039
				// Change the content
2040
				element.val( value );
2041
				element.trigger( "keyup" );
2042
 
2043
				setTimeout( function() {
2044
					assert.equal( validator.numberOfInvalids(), 1, "There is only one invalid element" );
2045
					assert.equal( validator.invalidElements()[ 0 ], element[ 0 ], "The val2 element should be invalid" );
2046
					done();
2047
				} );
2048
			} );
2049
		};
2050
 
2051
	check( "abc" );
2052
} );
2053
 
2054
QUnit.test( "validate checkbox on click", function( assert ) {
2055
	function errors( expected, message ) {
2056
		assert.equal( v.size(), expected, message );
2057
	}
2058
	function trigger( element ) {
2059
		element.click();
2060
 
2061
		// Triggered click event screws up checked-state in 1.4
2062
		element.valid();
2063
	}
2064
	var e = $( "#check2" ),
2065
		v = $( "#form" ).validate( {
2066
			rules: {
2067
				check2: "required"
2068
			}
2069
		} );
2070
 
2071
	trigger( e );
2072
	errors( 0 );
2073
	trigger( e );
2074
	assert.equal( v.form(), false );
2075
	errors( 1 );
2076
	trigger( e );
2077
	errors( 0 );
2078
	trigger( e );
2079
	errors( 1 );
2080
} );
2081
 
2082
QUnit.test( "validate multiple checkbox on click", function( assert ) {
2083
	function errors( expected, message ) {
2084
		assert.equal( v.size(), expected, message );
2085
	}
2086
	function trigger( element ) {
2087
		element.click();
2088
 
2089
		// Triggered click event screws up checked-state in 1.4
2090
		element.valid();
2091
	}
2092
	var e1 = $( "#check1" ).attr( "checked", false ),
2093
		e2 = $( "#check1b" ),
2094
		v = $( "#form" ).validate( {
2095
			rules: {
2096
				check: {
2097
					required: true,
2098
					minlength: 2
2099
				}
2100
			}
2101
		} );
2102
 
2103
	trigger( e1 );
2104
	trigger( e2 );
2105
	errors( 0 );
2106
	trigger( e2 );
2107
	assert.equal( v.form(), false );
2108
	errors( 1 );
2109
	trigger( e2 );
2110
	errors( 0 );
2111
	trigger( e2 );
2112
	errors( 1 );
2113
} );
2114
 
2115
QUnit.test( "correct checkbox receives the error", function( assert ) {
2116
	function trigger( element ) {
2117
		element.click();
2118
 
2119
		// Triggered click event screws up checked-state in 1.4
2120
		element.valid();
2121
	}
2122
	var e1 = $( "#check1" ).attr( "checked", false ),
2123
		v;
2124
 
2125
	$( "#check1b" ).attr( "checked", false );
2126
	v = $( "#form" ).find( "[type=checkbox]" ).attr( "checked", false ).end().validate( {
2127
		rules: {
2128
			check: {
2129
				required: true,
2130
				minlength: 2
2131
			}
2132
		}
2133
	} );
2134
 
2135
	assert.equal( v.form(), false );
2136
	trigger( e1 );
2137
	assert.equal( v.form(), false );
2138
	assert.ok( v.errorList[ 0 ].element.id === v.currentElements[ 0 ].id, "the proper checkbox has the error AND is present in currentElements" );
2139
} );
2140
 
2141
QUnit.test( "validate radio on click", function( assert ) {
2142
	function errors( expected, message ) {
2143
		assert.equal( v.size(), expected, message );
2144
	}
2145
	function trigger( element ) {
2146
		element.click();
2147
 
2148
		// Triggered click event screws up checked-state in 1.4
2149
		element.valid();
2150
	}
2151
	var e1 = $( "#radio1" ),
2152
		e2 = $( "#radio1a" ),
2153
		v = $( "#form" ).validate( {
2154
			rules: {
2155
				radio1: "required"
2156
			}
2157
		} );
2158
 
2159
	errors( 0 );
2160
	assert.equal( v.form(), false );
2161
	errors( 1 );
2162
	trigger( e2 );
2163
	errors( 0 );
2164
	trigger( e1 );
2165
	errors( 0 );
2166
} );
2167
 
2168
QUnit.test( "validate input with no type attribute, defaulting to text", function( assert ) {
2169
	function errors( expected, message ) {
2170
		assert.equal( v.size(), expected, message );
2171
	}
2172
	var v = $( "#testForm12" ).validate(),
2173
		e = $( "#testForm12text" );
2174
 
2175
	errors( 0 );
2176
	e.valid();
2177
	errors( 1 );
2178
	e.val( "test" );
2179
	e.trigger( "keyup" );
2180
	errors( 0 );
2181
} );
2182
 
2183
QUnit.module( "ignore hidden" );
2184
 
2185
QUnit.test( "ignore hidden elements", function( assert ) {
2186
	var form = $( "#userForm" ),
2187
		validate = form.validate( {
2188
			rules: {
2189
				"username": "required"
2190
			}
2191
		} );
2192
 
2193
	form.get( 0 ).reset();
2194
	assert.ok( !validate.form(), "form should be initially invalid" );
2195
	$( "#userForm [name=username]" ).hide();
2196
	assert.ok( validate.form(), "hidden elements should be ignored by default" );
2197
} );
2198
 
2199
QUnit.test( "ignore hidden elements at start", function( assert ) {
2200
	var form = $( "#userForm" ),
2201
		validate = form.validate( {
2202
			rules: {
2203
				"username": "required"
2204
			}
2205
		} );
2206
 
2207
	form.get( 0 ).reset();
2208
	$( "#userForm [name=username]" ).hide();
2209
	assert.ok( validate.form(), "hidden elements should be ignored by default" );
2210
	$( "#userForm [name=username]" ).show();
2211
	assert.ok( !validate.form(), "form should be invalid when required element is visible" );
2212
} );
2213
 
2214
QUnit.module( "configuration with attributes " );
2215
 
2216
QUnit.test( "Specify error messages through data attributes", function( assert ) {
2217
	var form = $( "#dataMessages" ),
2218
		name = $( "#dataMessagesName" ),
2219
		label;
2220
 
2221
	form.validate();
2222
 
2223
	form.get( 0 ).reset();
2224
	name.valid();
2225
 
2226
	label = $( "#dataMessages .error:not(input)" );
2227
	assert.equal( label.text(), "You must enter a value here", "Correct error label" );
2228
} );
2229
 
2230
QUnit.test( "Updates pre-existing label if has error class", function( assert ) {
2231
	var form = $( "#updateLabel" ),
2232
		input = $( "#updateLabelInput" ),
2233
		label = $( "#targetLabel" ),
2234
		labelsBefore = form.find( ".error:not(input)" ).length,
2235
		labelsAfter;
2236
 
2237
	form.validate();
2238
	input.val( "" );
2239
	input.valid();
2240
	labelsAfter = form.find( ".error:not(input)" ).length;
2241
 
2242
	// 'label' was updated
2243
	assert.equal( label.text(), input.attr( "data-msg-required" ) );
2244
 
2245
	// New label wasn't created
2246
	assert.equal( labelsAfter, labelsBefore );
2247
} );
2248
 
2249
QUnit.test( "Min date set by attribute", function( assert ) {
2250
	var form = $( "#rangesMinDateInvalid" ),
2251
		name = $( "#minDateInvalid" ),
2252
		label;
2253
 
2254
	form.validate();
2255
	form.get( 0 ).reset();
2256
	name.valid();
2257
 
2258
	label = $( "#rangesMinDateInvalid .error:not(input)" );
2259
	assert.equal( label.text(), "Please enter a value greater than or equal to 2012-12-21.", "Correct error label" );
2260
} );
2261
 
2262
QUnit.test( "Max date set by attribute", function( assert ) {
2263
	var form = $( "#ranges" ),
2264
		name = $( "#maxDateInvalid" ),
2265
		label;
2266
 
2267
	form.validate();
2268
	form.get( 0 ).reset();
2269
	name.valid();
2270
 
2271
	label = $( "#ranges .error:not(input)" );
2272
	assert.equal( label.text(), "Please enter a value less than or equal to 2012-12-21.", "Correct error label" );
2273
} );
2274
 
2275
QUnit.test( "Min and Max date set by attributes greater", function( assert ) {
2276
	var form = $( "#ranges" ),
2277
		name = $( "#rangeDateInvalidGreater" ),
2278
		label;
2279
 
2280
	form.validate();
2281
	form.get( 0 ).reset();
2282
	name.valid();
2283
 
2284
	label = $( "#ranges .error:not(input)" );
2285
	assert.equal( label.text(), "Please enter a value less than or equal to 2013-01-21.", "Correct error label" );
2286
} );
2287
 
2288
QUnit.test( "Min and Max date set by attributes less", function( assert ) {
2289
	var form = $( "#ranges" ),
2290
		name = $( "#rangeDateInvalidLess" ),
2291
		label;
2292
 
2293
	form.validate();
2294
	form.get( 0 ).reset();
2295
	name.valid();
2296
 
2297
	label = $( "#ranges .error:not(input)" );
2298
	assert.equal( label.text(), "Please enter a value greater than or equal to 2012-11-21.", "Correct error label" );
2299
} );
2300
 
2301
QUnit.test( "Min date set by attribute valid", function( assert ) {
2302
	var form = $( "#rangeMinDateValid" ),
2303
		name = $( "#minDateValid" ),
2304
		label;
2305
 
2306
	form.validate();
2307
	form.get( 0 ).reset();
2308
	name.valid();
2309
 
2310
	label = $( "#rangeMinDateValid .error:not(input)" );
2311
	assert.equal( label.text(), "", "Correct error label" );
2312
} );
2313
 
2314
QUnit.test( "Max date set by attribute valid", function( assert ) {
2315
	var form = $( "#ranges" ),
2316
		name = $( "#maxDateValid" ),
2317
		label;
2318
 
2319
	form.validate();
2320
	form.get( 0 ).reset();
2321
	name.valid();
2322
 
2323
	label = $( "#ranges .error:not(input)" );
2324
	assert.equal( label.text(), "", "Correct error label" );
2325
} );
2326
 
2327
QUnit.test( "Min and Max date set by attributes valid", function( assert ) {
2328
	var form = $( "#ranges" ),
2329
		name = $( "#rangeDateValid" ),
2330
		label;
2331
 
2332
	form.validate();
2333
	form.get( 0 ).reset();
2334
	name.valid();
2335
 
2336
	label = $( "#ranges .error:not(input)" );
2337
	assert.equal( label.text(), "", "Correct error label" );
2338
} );
2339
 
2340
QUnit.test( "Min and Max strings set by attributes greater", function( assert ) {
2341
	var form = $( "#ranges" ),
2342
		name = $( "#rangeTextInvalidGreater" ),
2343
		label;
2344
 
2345
	form.validate();
2346
	form.get( 0 ).reset();
2347
	name.valid();
2348
 
2349
	label = $( "#ranges .error:not(input)" );
2350
	assert.equal( label.text(), "Please enter a value less than or equal to 200.", "Correct error label" );
2351
} );
2352
 
2353
QUnit.test( "Min and Max strings set by attributes less", function( assert ) {
2354
	var form = $( "#ranges" ),
2355
		name = $( "#rangeTextInvalidLess" ),
2356
		label;
2357
 
2358
	form.validate();
2359
	form.get( 0 ).reset();
2360
	name.valid();
2361
 
2362
	label = $( "#ranges .error:not(input)" );
2363
	assert.equal( label.text(), "Please enter a value greater than or equal to 200.", "Correct error label" );
2364
} );
2365
 
2366
QUnit.test( "Step string set by attribute invalid", function( assert ) {
2367
	var form = $( "#ranges" ),
2368
		name = $( "#rangeTextInvalidStep" ),
2369
		label;
2370
 
2371
	form.validate();
2372
	form.get( 0 ).reset();
2373
	name.valid();
2374
 
2375
	label = $( "#ranges .error:not(input)" );
2376
	assert.equal( label.text(), "Please enter a multiple of 100.", "Correct error label" );
2377
} );
2378
 
2379
QUnit.test( "Min, Max and Step strings set by attributes valid", function( assert ) {
2380
	var form = $( "#ranges" ),
2381
		range = $( "#rangeTextValid" ),
2382
		label;
2383
 
2384
	form.validate();
2385
	form.get( 0 ).reset();
2386
	range.valid();
2387
 
2388
	label = $( "#ranges .error:not(input)" );
2389
	assert.equal( label.text(), "", "Correct error label" );
2390
} );
2391
 
2392
QUnit.test( "Min, Max and Step set by data-rule valid", function( assert ) {
2393
	var form = $( "#ranges" ),
2394
		range = $( "#rangeTextDataRuleValid" ),
2395
		label;
2396
 
2397
	form.validate();
2398
	form.get( 0 ).reset();
2399
	range.valid();
2400
 
2401
	label = $( "#ranges .error:not(input)" );
2402
	assert.equal( label.text(), "", "Correct error label" );
2403
} );
2404
 
2405
QUnit.test( "Step attribute on element with unsupported input type", function( assert ) {
2406
	var form = $( "#stepOnUnsupportedType" ),
2407
		input = $( "#stepOnUnsupportedTypeInput" );
2408
 
2409
	assert.throws(
2410
		function() {
2411
			form.validate();
2412
			form.get( 0 ).reset();
2413
			input.valid();
2414
		},
2415
		function( err ) {
2416
			return err.message === "Step attribute on input type date is not supported.";
2417
		},
2418
		"Must throw an expected error to pass."
2419
	);
2420
} );
2421
 
2422
QUnit.test( "calling blur on ignored element", function( assert ) {
2423
	var form = $( "#ignoredElements" );
2424
 
2425
	form.validate( {
2426
		ignore: ".ignore",
2427
		invalidHandler: function() {
2428
			$( "#ss1" ).blur();
2429
		}
2430
	} );
2431
 
2432
	form.trigger( "submit" );
2433
	assert.equal( form.valid(), false, "valid() should return false" );
2434
} );
2435
 
2436
QUnit.test( "Min and Max type absent set by attributes greater", function( assert ) {
2437
	var form = $( "#ranges" ),
2438
		name = $( "#rangeAbsentInvalidGreater" ),
2439
		label;
2440
 
2441
	form.validate();
2442
	form.get( 0 ).reset();
2443
	name.valid();
2444
 
2445
	label = $( "#ranges .error:not(input)" );
2446
	assert.equal( label.text(), "Please enter a value less than or equal to 200.", "Correct error label" );
2447
} );
2448
 
2449
QUnit.test( "Min and Max type absent set by attributes less", function( assert ) {
2450
	var form = $( "#ranges" ),
2451
		name = $( "#rangeAbsentInvalidLess" ),
2452
		label;
2453
 
2454
	form.validate();
2455
	form.get( 0 ).reset();
2456
	name.valid();
2457
 
2458
	label = $( "#ranges .error:not(input)" );
2459
	assert.equal( label.text(), "Please enter a value greater than or equal to 200.", "Correct error label" );
2460
} );
2461
 
2462
QUnit.test( "Step type absent set by attribute invalid", function( assert ) {
2463
	var form = $( "#ranges" ),
2464
		name = $( "#rangeAbsentInvalidStep" ),
2465
		label;
2466
 
2467
	form.validate();
2468
	form.get( 0 ).reset();
2469
	name.valid();
2470
 
2471
	label = $( "#ranges .error:not(input)" );
2472
	assert.equal( label.text(), "Please enter a multiple of 100.", "Correct error label" );
2473
} );
2474
 
2475
QUnit.test( "Min, Max and Step type absent set by attributes valid", function( assert ) {
2476
	var form = $( "#ranges" ),
2477
		name = $( "#rangeAbsentValid" ),
2478
		label;
2479
 
2480
	form.validate();
2481
	form.get( 0 ).reset();
2482
	name.valid();
2483
 
2484
	label = $( "#ranges .error:not(input)" );
2485
	assert.equal( label.text(), "", "Correct error label" );
2486
} );
2487
 
2488
QUnit.test( "Min, Max and Step range set by attributes valid", function( assert ) {
2489
 
2490
	//
2491
	// Cannot test for overflow:
2492
	// When the element is suffering from an underflow,
2493
	// the user agent must set the element"s value to a valid
2494
	// floating-point number that represents the minimum.
2495
	// http://www.w3.org/TR/html5/forms.html#range-state-%28type=range%29
2496
	//
2497
	var form = $( "#ranges" ),
2498
		name = $( "#rangeRangeValid" ),
2499
		label;
2500
 
2501
	form.validate();
2502
	form.get( 0 ).reset();
2503
	name.valid();
2504
 
2505
	label = $( "#ranges .error:not(input)" );
2506
	assert.equal( label.text(), "", "Correct error label" );
2507
} );
2508
 
2509
QUnit.test( "Min and Max number set by attributes valid", function( assert ) {
2510
	var form = $( "#ranges" ),
2511
		name = $( "#rangeNumberValid" ),
2512
		label;
2513
 
2514
	form.validate();
2515
	form.get( 0 ).reset();
2516
	name.valid();
2517
 
2518
	label = $( "#ranges .error:not(input)" );
2519
	assert.equal( label.text(), "", "Correct error label" );
2520
} );
2521
 
2522
QUnit.test( "Min and Max number set by attributes greater", function( assert ) {
2523
	var form = $( "#ranges" ),
2524
		name = $( "#rangeNumberInvalidGreater" ),
2525
		label;
2526
 
2527
	form.validate();
2528
	form.get( 0 ).reset();
2529
	name.valid();
2530
 
2531
	label = $( "#ranges .error:not(input)" );
2532
	assert.equal( label.text(), "Please enter a value less than or equal to 200.", "Correct error label" );
2533
} );
2534
 
2535
QUnit.test( "Min and Max number set by attributes less", function( assert ) {
2536
	var form = $( "#ranges" ),
2537
		name = $( "#rangeNumberInvalidLess" ),
2538
		label;
2539
 
2540
	form.validate();
2541
	form.get( 0 ).reset();
2542
	name.valid();
2543
 
2544
	label = $( "#ranges .error:not(input)" );
2545
	assert.equal( label.text(), "Please enter a value greater than or equal to 50.", "Correct error label" );
2546
} );
2547
 
2548
QUnit.test( "Rules allowed to have a value of zero invalid", function( assert ) {
2549
	var form = $( "#ranges" ),
2550
		name = $( "#rangeMinZeroInvalidLess" ),
2551
		label;
2552
 
2553
	form.validate();
2554
	form.get( 0 ).reset();
2555
	name.valid();
2556
 
2557
	label = $( "#ranges .error:not(input)" );
2558
	assert.equal( label.text(), "Please enter a value greater than or equal to 0.", "Correct error label" );
2559
} );
2560
 
2561
QUnit.test( "Rules allowed to have a value of zero valid equal", function( assert ) {
2562
	var form = $( "#ranges" ),
2563
		name = $( "#rangeMinZeroValidEqual" ),
2564
		label;
2565
 
2566
	form.validate();
2567
	form.get( 0 ).reset();
2568
	name.valid();
2569
 
2570
	label = $( "#ranges .error:not(input)" );
2571
	assert.equal( label.text(), "", "Correct error label" );
2572
} );
2573
 
2574
QUnit.test( "Rules allowed to have a value of zero valid greater", function( assert ) {
2575
	var form = $( "#ranges" ),
2576
		name = $( "#rangeMinZeroValidGreater" ),
2577
		label;
2578
 
2579
	form.validate();
2580
	form.get( 0 ).reset();
2581
	name.valid();
2582
 
2583
	label = $( "#ranges .error:not(input)" );
2584
	assert.equal( label.text(), "", "Correct error label" );
2585
} );
2586
 
2587
QUnit.test( "Validation triggered on radio and checkbox via click", function( assert ) {
2588
	assert.expect( 2 );
2589
 
2590
	var form = $( "#radiocheckbox" );
2591
 
2592
	// Init validate
2593
	form.validate();
2594
 
2595
	// Validate so we have errors
2596
	assert.ok( !form.valid(), "Form invalid" );
2597
 
2598
	// Simulate native click on first checkbox to trigger change-event
2599
	$( "#radiocheckbox-0-1" ).simulate( "click" );
2600
 
2601
	// Simulate native click on first radio to trigger change-event
2602
	$( "#radiocheckbox-1-1" ).simulate( "click" );
2603
 
2604
	// Test if there is no error anymore
2605
	assert.ok( form.find( "input.error" ).length === 0, "Form valid" );
2606
} );
2607
 
2608
QUnit.test( "destroy()", function( assert ) {
2609
	assert.expect( 14 );
2610
 
2611
	var form = $( "#testForm5" ),
2612
		validate = form.validate();
2613
 
2614
	assert.strictEqual( form.data( "validator" ), validate );
2615
 
2616
	form.valid();
2617
	assert.equal( $( "#x1", form ).hasClass( "validate-equalTo-blur" ), true, "The blur event should be bound to this element" );
2618
	assert.equal( $( "#x2", form ).hasClass( "validate-equalTo-blur" ), true, "The blur event should be bound to this element" );
2619
 
2620
	assert.equal( $( "#y1", form ).hasClass( "validate-greaterThan-blur" ), true, "The blur event should be bound to this element" );
2621
	assert.equal( $( "#y2", form ).hasClass( "validate-lessThan-blur" ), true, "The blur event should be bound to this element" );
2622
	assert.equal( $( "#z1", form ).hasClass( "validate-greaterThanEqual-blur" ), true, "The blur event should be bound to this element" );
2623
	assert.equal( $( "#z2", form ).hasClass( "validate-lessThanEqual-blur" ), true, "The blur event should be bound to this element" );
2624
 
2625
	validate.destroy();
2626
	assert.strictEqual( form.data( "validator" ), undefined );
2627
	assert.equal( $( "#x1", form ).hasClass( "validate-equalTo-blur" ), false, "The blur event should be unbound from this element" );
2628
	assert.equal( $( "#x2", form ).hasClass( "validate-equalTo-blur" ), false, "The blur event should be unbound from this element" );
2629
 
2630
	assert.equal( $( "#y1", form ).hasClass( "validate-lessThan-blur" ), false, "The blur event should be unbound from this element" );
2631
	assert.equal( $( "#y2", form ).hasClass( "validate-greaterThan-blur" ), false, "The blur event should be unbound from this element" );
2632
	assert.equal( $( "#z1", form ).hasClass( "validate-equalTo-blur" ), false, "The blur event should be unbound from this element" );
2633
	assert.equal( $( "#z2", form ).hasClass( "validate-greaterThan-blur" ), false, "The blur event should be unbound from this element" );
2634
 
2635
} );
2636
 
2637
QUnit.test( "#1618: Errorlist containing more errors than it should", function( assert ) {
2638
	var v = $( "#testForm24" ).validate( {
2639
			rules: {
2640
				val1: {
2641
					required: true
2642
				},
2643
				val2: {
2644
					required: true
2645
				},
2646
				val3: {
2647
					required: true
2648
				}
2649
			}
2650
		} ),
2651
		inputList = $( "#val1, #val2, #val3" );
2652
 
2653
	inputList.valid();
2654
	assert.equal( v.errorList.length, 2, "There is only two errors" );
2655
 
2656
	inputList.valid();
2657
	assert.equal( v.errorList.length, 2, "There should be no change in errorList's content" );
2658
} );
2659
 
2660
QUnit.test( "addMethod, reusing remote in custom method", function( assert ) {
2661
	assert.expect( 7 );
2662
	$.validator.addMethod( "workemail", function( value, element, param ) {
2663
		return $.validator.methods.remote.call( this, value, element, {
2664
			url: "workemail.php",
2665
			data: { email: value, special: param }
2666
		}, "workemail" );
2667
	}, "work email custom message" );
2668
 
2669
	var e = $( "#add-method-username" ),
2670
		v = $( "#add-method-remote" ).validate(),
2671
		done = assert.async();
2672
 
2673
	$( document ).ajaxStop( function() {
2674
		$( document ).unbind( "ajaxStop" );
2675
		assert.strictEqual( v.size(), 1, "There must be one error" );
2676
		assert.strictEqual( v.errorList[ 0 ].message, "work email custom message", "john.doe@gmail.com is not work email" );
2677
 
2678
		$( document ).ajaxStop( function() {
2679
			$( document ).unbind( "ajaxStop" );
2680
			assert.strictEqual( v.size(), 0, "There must be no errors" );
2681
			assert.ok( v.element( e ), "john.doe@company.com is work email ;)" );
2682
			done();
2683
		} );
2684
		e.val( "john.doe@company.com" );
2685
		assert.strictEqual( v.element( e ), true, "new value, new request; dependency-mismatch considered as valid though" );
2686
	} );
2687
	assert.strictEqual( v.element( e ), false, "invalid element, nothing entered yet" );
2688
	e.val( "john.doe@gmail.com" );
2689
	assert.strictEqual( v.element( e ), true, "still invalid, because remote validation must block until it returns; dependency-mismatch considered as valid though" );
2690
} );