error-placement.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. QUnit.module( "placement" );
  2. QUnit.test( "elements() order", function( assert ) {
  3. var container = $( "#orderContainer" ),
  4. v = $( "#elementsOrder" ).validate( {
  5. errorLabelContainer: container,
  6. wrap: "li"
  7. } );
  8. assert.deepEqual(
  9. v.elements().map( function() {
  10. return $( this ).attr( "id" );
  11. } ).get(),
  12. [
  13. "order1",
  14. "order2",
  15. "order3",
  16. "order4",
  17. "order5",
  18. "order6"
  19. ],
  20. "elements must be in document order"
  21. );
  22. v.form();
  23. assert.deepEqual(
  24. container.children().map( function() {
  25. return $( this ).attr( "id" );
  26. } ).get(),
  27. [
  28. "order1-error",
  29. "order2-error",
  30. "order3-error",
  31. "order4-error",
  32. "order5-error",
  33. "order6-error"
  34. ],
  35. "labels in error container must be in document order"
  36. );
  37. } );
  38. QUnit.test( "error containers, simple", function( assert ) {
  39. assert.expect( 14 );
  40. var container = $( "#simplecontainer" ),
  41. v = $( "#form" ).validate( {
  42. errorLabelContainer: container,
  43. showErrors: function() {
  44. container.find( "h3" ).html( jQuery.validator.format( "There are {0} errors in your form.", this.size() ) );
  45. this.defaultShowErrors();
  46. }
  47. } );
  48. v.prepareForm();
  49. assert.ok( v.valid(), "form is valid" );
  50. assert.equal( container.find( ".error:not(input)" ).length, 0, "There should be no error labels" );
  51. assert.equal( container.find( "h3" ).html(), "" );
  52. v.prepareForm();
  53. v.errorList = [
  54. {
  55. message: "bar",
  56. element: {
  57. name: "foo"
  58. }
  59. },
  60. {
  61. message: "necessary",
  62. element: {
  63. name: "required"
  64. }
  65. }
  66. ];
  67. assert.ok( !v.valid(), "form is not valid after adding errors manually" );
  68. v.showErrors();
  69. assert.equal( container.find( ".error:not(input)" ).length, 2, "There should be two error labels" );
  70. assert.ok( container.is( ":visible" ), "Check that the container is visible" );
  71. container.find( ".error:not(input)" ).each( function() {
  72. assert.ok( $( this ).is( ":visible" ), "Check that each label is visible" );
  73. } );
  74. assert.equal( container.find( "h3" ).html(), "There are 2 errors in your form." );
  75. v.prepareForm();
  76. assert.ok( v.valid(), "form is valid after a reset" );
  77. v.showErrors();
  78. assert.equal( container.find( ".error:not(input)" ).length, 2, "There should still be two error labels" );
  79. assert.ok( container.is( ":hidden" ), "Check that the container is hidden" );
  80. container.find( ".error:not(input)" ).each( function() {
  81. assert.ok( $( this ).is( ":hidden" ), "Check that each label is hidden" );
  82. } );
  83. } );
  84. QUnit.test( "error containers, with labelcontainer I", function( assert ) {
  85. assert.expect( 16 );
  86. var container = $( "#container" ),
  87. labelcontainer = $( "#labelcontainer" ),
  88. v = $( "#form" ).validate( {
  89. errorContainer: container,
  90. errorLabelContainer: labelcontainer,
  91. wrapper: "li"
  92. } );
  93. assert.ok( v.valid(), "form is valid" );
  94. assert.equal( container.find( ".error:not(input)" ).length, 0, "There should be no error labels in the container" );
  95. assert.equal( labelcontainer.find( ".error:not(input)" ).length, 0, "There should be no error labels in the labelcontainer" );
  96. assert.equal( labelcontainer.find( "li" ).length, 0, "There should be no lis labels in the labelcontainer" );
  97. v.errorList = [
  98. {
  99. message: "bar",
  100. element: {
  101. name: "foo"
  102. }
  103. },
  104. {
  105. name: "required",
  106. message: "necessary",
  107. element: {
  108. name: "required"
  109. }
  110. }
  111. ];
  112. assert.ok( !v.valid(), "form is not valid after adding errors manually" );
  113. v.showErrors();
  114. assert.equal( container.find( ".error:not(input)" ).length, 0, "There should be no error label in the container" );
  115. assert.equal( labelcontainer.find( ".error:not(input)" ).length, 2, "There should be two error labels in the labelcontainer" );
  116. assert.equal( labelcontainer.find( "li" ).length, 2, "There should be two error lis in the labelcontainer" );
  117. assert.ok( container.is( ":visible" ), "Check that the container is visible" );
  118. assert.ok( labelcontainer.is( ":visible" ), "Check that the labelcontainer is visible" );
  119. labelcontainer.find( ".error:not(input)" ).each( function() {
  120. assert.ok( $( this ).is( ":visible" ), "Check that each label is visible1" );
  121. assert.equal( $( this ).parent()[ 0 ].tagName.toLowerCase(), "li", "Check that each label is wrapped in an li" );
  122. assert.ok( $( this ).parent( "li" ).is( ":visible" ), "Check that each parent li is visible" );
  123. } );
  124. } );
  125. QUnit.test( "errorcontainer, show/hide only on submit", function( assert ) {
  126. assert.expect( 14 );
  127. var container = $( "#container" ),
  128. labelContainer = $( "#labelcontainer" ),
  129. v = $( "#testForm1" ).bind( "invalid-form.validate", function() {
  130. assert.ok( true, "invalid-form event triggered called" );
  131. } ).validate( {
  132. errorContainer: container,
  133. errorLabelContainer: labelContainer,
  134. showErrors: function() {
  135. container.html( jQuery.validator.format( "There are {0} errors in your form.", this.numberOfInvalids() ) );
  136. assert.ok( true, "showErrors called" );
  137. this.defaultShowErrors();
  138. }
  139. } );
  140. assert.equal( container.html(), "", "must be empty" );
  141. assert.equal( labelContainer.html(), "", "must be empty" );
  142. // Validate whole form, both showErrors and invalidHandler must be called once
  143. // preferably invalidHandler first, showErrors second
  144. assert.ok( !v.form(), "invalid form" );
  145. assert.equal( labelContainer.find( ".error:not(input)" ).length, 2 );
  146. assert.equal( container.html(), "There are 2 errors in your form." );
  147. assert.ok( labelContainer.is( ":visible" ), "must be visible" );
  148. assert.ok( container.is( ":visible" ), "must be visible" );
  149. $( "#firstname" ).val( "hix" ).keyup();
  150. $( "#testForm1" ).triggerHandler( "keyup", [
  151. jQuery.event.fix( {
  152. type: "keyup",
  153. target: $( "#firstname" )[ 0 ]
  154. } )
  155. ] );
  156. assert.equal( labelContainer.find( ".error:visible" ).length, 1 );
  157. assert.equal( container.html(), "There are 1 errors in your form." );
  158. $( "#lastname" ).val( "abc" );
  159. assert.ok( v.form(), "Form now valid, trigger showErrors but not invalid-form" );
  160. } );
  161. QUnit.test( "test label used as error container", function( assert ) {
  162. assert.expect( 8 );
  163. var form = $( "#testForm16" ),
  164. field = $( "#testForm16text" );
  165. form.validate( {
  166. errorPlacement: function( error, element ) {
  167. // Append error within linked label
  168. $( "label[for='" + element.attr( "id" ) + "']" ).append( error );
  169. },
  170. errorElement: "span"
  171. } );
  172. assert.ok( !field.valid() );
  173. assert.equal( field.next( "label" ).contents().first().text(), "Field Label", "container label isn't disrupted" );
  174. assert.hasError( field, "missing" );
  175. assert.ok( !field.attr( "aria-describedby" ), "field does not require aria-describedby attribute" );
  176. field.val( "foo" );
  177. assert.ok( field.valid() );
  178. assert.equal( field.next( "label" ).contents().first().text(), "Field Label", "container label isn't disrupted" );
  179. assert.ok( !field.attr( "aria-describedby" ), "field does not require aria-describedby attribute" );
  180. assert.noErrorFor( field );
  181. } );
  182. QUnit.test( "test error placed adjacent to descriptive label", function( assert ) {
  183. assert.expect( 8 );
  184. var form = $( "#testForm16" ),
  185. field = $( "#testForm16text" );
  186. form.validate( {
  187. errorElement: "span"
  188. } );
  189. assert.ok( !field.valid() );
  190. assert.equal( form.find( "label" ).length, 1 );
  191. assert.equal( form.find( "label" ).text(), "Field Label", "container label isn't disrupted" );
  192. assert.hasError( field, "missing" );
  193. field.val( "foo" );
  194. assert.ok( field.valid() );
  195. assert.equal( form.find( "label" ).length, 1 );
  196. assert.equal( form.find( "label" ).text(), "Field Label", "container label isn't disrupted" );
  197. assert.noErrorFor( field );
  198. } );
  199. QUnit.test( "test descriptive label used alongside error label", function( assert ) {
  200. assert.expect( 8 );
  201. var form = $( "#testForm16" ),
  202. field = $( "#testForm16text" );
  203. form.validate( {
  204. errorElement: "label"
  205. } );
  206. assert.ok( !field.valid() );
  207. assert.equal( form.find( "label.title" ).length, 1 );
  208. assert.equal( form.find( "label.title" ).text(), "Field Label", "container label isn't disrupted" );
  209. assert.hasError( field, "missing" );
  210. field.val( "foo" );
  211. assert.ok( field.valid() );
  212. assert.equal( form.find( "label.title" ).length, 1 );
  213. assert.equal( form.find( "label.title" ).text(), "Field Label", "container label isn't disrupted" );
  214. assert.noErrorFor( field );
  215. } );
  216. QUnit.test( "test custom errorElement", function( assert ) {
  217. assert.expect( 4 );
  218. var form = $( "#userForm" ),
  219. field = $( "#username" );
  220. form.validate( {
  221. messages: {
  222. username: "missing"
  223. },
  224. errorElement: "label"
  225. } );
  226. assert.ok( !field.valid() );
  227. assert.hasError( field, "missing", "Field should have error 'missing'" );
  228. field.val( "foo" );
  229. assert.ok( field.valid() );
  230. assert.noErrorFor( field, "Field should not have a visible error" );
  231. } );
  232. QUnit.test( "test existing label used as error element", function( assert ) {
  233. assert.expect( 4 );
  234. var form = $( "#testForm14" ),
  235. field = $( "#testForm14text" );
  236. form.validate( { errorElement: "label" } );
  237. assert.ok( !field.valid() );
  238. assert.hasError( field, "required" );
  239. field.val( "foo" );
  240. assert.ok( field.valid() );
  241. assert.noErrorFor( field );
  242. } );
  243. QUnit.test( "test existing non-label used as error element", function( assert ) {
  244. assert.expect( 4 );
  245. var form = $( "#testForm15" ),
  246. field = $( "#testForm15text" );
  247. form.validate( { errorElement: "span" } );
  248. assert.ok( !field.valid() );
  249. assert.hasError( field, "required" );
  250. field.val( "foo" );
  251. assert.ok( field.valid() );
  252. assert.noErrorFor( field );
  253. } );
  254. QUnit.test( "test aria-describedby with input names contains CSS-selector meta-characters", function( assert ) {
  255. var form = $( "#testForm21" ),
  256. field = $( "#testForm21\\!\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\`\\{\\|\\}\\~" );
  257. assert.equal( field.attr( "aria-describedby" ), undefined );
  258. form.validate( {
  259. errorElement: "span",
  260. errorPlacement: function() {
  261. // Do something
  262. }
  263. } );
  264. // Validate the element
  265. assert.ok( !field.valid() );
  266. assert.equal( field.attr( "aria-describedby" ), "testForm21!#$%&'()*+,./:;<=>?@[\\]^`{|}~-error" );
  267. // Re-run validation
  268. field.val( "some" );
  269. field.trigger( "keyup" );
  270. field.val( "something" );
  271. field.trigger( "keyup" );
  272. assert.equal( field.attr( "aria-describedby" ), "testForm21!#$%&'()*+,./:;<=>?@[\\]^`{|}~-error", "`aria-describedby` should remain the same as before." );
  273. // Re-run validation
  274. field.val( "something something" );
  275. field.trigger( "keyup" );
  276. assert.ok( field.valid() );
  277. assert.equal( field.attr( "aria-describedby" ), "testForm21!#$%&'()*+,./:;<=>?@[\\]^`{|}~-error", "`aria-describedby` should remain the same as before." );
  278. } );
  279. QUnit.test( "test existing non-error aria-describedby", function( assert ) {
  280. assert.expect( 8 );
  281. var form = $( "#testForm17" ),
  282. field = $( "#testForm17text" );
  283. assert.equal( field.attr( "aria-describedby" ), "testForm17text-description" );
  284. form.validate( { errorElement: "span" } );
  285. assert.ok( !field.valid() );
  286. assert.equal( field.attr( "aria-describedby" ), "testForm17text-description testForm17text-error" );
  287. assert.hasError( field, "required" );
  288. field.val( "foo" );
  289. assert.ok( field.valid() );
  290. assert.noErrorFor( field );
  291. assert.strictEqual( $( "#testForm17text-description" ).text(), "This is where you enter your data" );
  292. assert.strictEqual( $( "#testForm17text-error" ).text(), "", "Error label is empty for valid field" );
  293. } );
  294. QUnit.test( "test pre-assigned non-error aria-describedby", function( assert ) {
  295. assert.expect( 7 );
  296. var form = $( "#testForm17" ),
  297. field = $( "#testForm17text" );
  298. // Pre-assign error identifier
  299. field.attr( "aria-describedby", "testForm17text-description testForm17text-error" );
  300. form.validate( { errorElement: "span" } );
  301. assert.ok( !field.valid() );
  302. assert.equal( field.attr( "aria-describedby" ), "testForm17text-description testForm17text-error" );
  303. assert.hasError( field, "required" );
  304. field.val( "foo" );
  305. assert.ok( field.valid() );
  306. assert.noErrorFor( field );
  307. assert.strictEqual( $( "#testForm17text-description" ).text(), "This is where you enter your data" );
  308. assert.strictEqual( $( "#testForm17text-error" ).text(), "", "Error label is empty for valid field" );
  309. } );
  310. QUnit.test( "test id/name containing brackets", function( assert ) {
  311. var form = $( "#testForm18" ),
  312. field = $( "#testForm18\\[text\\]" );
  313. form.validate( {
  314. errorElement: "span"
  315. } );
  316. form.valid();
  317. field.valid();
  318. assert.hasError( field, "required" );
  319. } );
  320. QUnit.test( "test id/name containing $", function( assert ) {
  321. var form = $( "#testForm19" ),
  322. field = $( "#testForm19\\$text" );
  323. form.validate( {
  324. errorElement: "span"
  325. } );
  326. field.valid();
  327. assert.hasError( field, "required" );
  328. } );
  329. QUnit.test( "test id/name containing single quotes", function( assert ) {
  330. var v = $( "#testForm20" ).validate(),
  331. textElement = $( "#testForm20\\[\\'textinput\\'\\]" ),
  332. checkboxElement = $( "#testForm20\\[\\'checkboxinput\\'\\]" ),
  333. radioElement = $( "#testForm20\\[\\'radioinput\\'\\]" );
  334. v.form();
  335. assert.equal( v.numberOfInvalids(), 3, "There is three invalid elements" );
  336. assert.equal( v.invalidElements()[ 0 ], textElement[ 0 ], "The element should be invalid" );
  337. assert.equal( v.invalidElements()[ 1 ], checkboxElement[ 0 ], "The text element should be invalid" );
  338. assert.equal( v.invalidElements()[ 2 ], radioElement[ 0 ], "The text element should be invalid" );
  339. } );
  340. QUnit.test( "#1632: Error hidden, but input error class not removed", function( assert ) {
  341. var v = $( "#testForm23" ).validate( {
  342. rules: {
  343. box1: {
  344. required: {
  345. depends: function() {
  346. return !!$( "#box2" ).val();
  347. }
  348. }
  349. },
  350. box2: {
  351. required: {
  352. depends: function() {
  353. return !!$( "#box1" ).val();
  354. }
  355. }
  356. }
  357. }
  358. } ),
  359. box1 = $( "#box1" ),
  360. box2 = $( "#box2" );
  361. box1.val( "something" );
  362. v.form();
  363. assert.equal( v.numberOfInvalids(), 1, "There is only one invlid element" );
  364. assert.equal( v.invalidElements()[ 0 ], box2[ 0 ], "The box2 element should be invalid" );
  365. box1.val( "" );
  366. v.form();
  367. assert.equal( v.numberOfInvalids(), 0, "There is no error" );
  368. assert.equal( box2.hasClass( "error" ), false, "Box2 should not have an error class" );
  369. } );