/tests/nestedValidation.js

https://github.com/thedersen/backbone.validation · JavaScript · 479 lines · 399 code · 80 blank · 0 comment · 3 complexity · f5ff085426c76d98e9ff2bc29ab3496a MD5 · raw file

  1. buster.testCase('Nested validation', {
  2. "one level": {
  3. setUp: function() {
  4. this.valid = this.spy();
  5. this.invalid = this.spy();
  6. var Model = Backbone.Model.extend({
  7. validation: {
  8. 'address.street': {
  9. required: true,
  10. msg: 'error'
  11. }
  12. }
  13. });
  14. this.model = new Model();
  15. this.view = new Backbone.View({model: this.model});
  16. Backbone.Validation.bind(this.view, {
  17. invalid: this.invalid,
  18. valid: this.valid
  19. });
  20. },
  21. "invalid": {
  22. setUp: function () {
  23. this.result = this.model.set({
  24. address: {
  25. street:''
  26. }
  27. }, {validate: true});
  28. },
  29. "refutes setting invalid values": function() {
  30. refute(this.result);
  31. },
  32. "calls the invalid callback": function() {
  33. assert.calledWith(this.invalid, this.view, 'address.street', 'error');
  34. },
  35. "is valid returns false for the specified attribute name": function () {
  36. refute(this.model.isValid('address.street'));
  37. },
  38. "is valid returns false for the specified attribute names": function () {
  39. refute(this.model.isValid(['address.street', 'address.street']));
  40. },
  41. "pre validate returns error message for the specified attribute name": function () {
  42. assert(this.model.preValidate('address.street', ''));
  43. }
  44. },
  45. "valid": {
  46. setUp: function () {
  47. this.result = this.model.set({
  48. address: {
  49. street: 'name'
  50. }
  51. }, {validate: true});
  52. },
  53. "sets the value": function() {
  54. assert(this.result);
  55. },
  56. "calls the valid callback": function() {
  57. assert.calledWith(this.valid, this.view, 'address.street');
  58. },
  59. "is valid returns true for the specified attribute name": function () {
  60. assert(this.model.isValid('address.street'));
  61. },
  62. "is valid returns true for the specified attribute names": function () {
  63. assert(this.model.isValid(['address.street', 'address.street']));
  64. },
  65. "pre validate returns no error message for the specified attribute name": function () {
  66. refute(this.model.preValidate('address.street', 'street'));
  67. }
  68. }
  69. },
  70. "two levels": {
  71. setUp: function() {
  72. this.valid = this.spy();
  73. this.invalid = this.spy();
  74. var Model = Backbone.Model.extend({
  75. validation: {
  76. 'foo.bar.baz': {
  77. required: true,
  78. msg: 'error'
  79. }
  80. }
  81. });
  82. this.model = new Model();
  83. this.view = new Backbone.View({model: this.model});
  84. Backbone.Validation.bind(this.view, {
  85. invalid: this.invalid,
  86. valid: this.valid
  87. });
  88. },
  89. "invalid": {
  90. setUp: function () {
  91. this.result = this.model.set({
  92. foo: {
  93. bar: {
  94. baz: ''
  95. }
  96. }
  97. }, {validate: true});
  98. },
  99. "refutes setting invalid values": function() {
  100. refute(this.result);
  101. },
  102. "calls the invalid callback": function() {
  103. assert.calledWith(this.invalid, this.view, 'foo.bar.baz', 'error');
  104. },
  105. "is valid returns false for the specified attribute name": function () {
  106. refute(this.model.isValid('foo.bar.baz'));
  107. },
  108. "is valid returns false for the specified attribute names": function () {
  109. refute(this.model.isValid(['foo.bar.baz', 'foo.bar.baz']));
  110. },
  111. "pre validate returns error message for the specified attribute name": function () {
  112. assert(this.model.preValidate('foo.bar.baz', ''));
  113. }
  114. },
  115. "valid": {
  116. setUp: function () {
  117. this.result = this.model.set({
  118. foo: {
  119. bar: {
  120. baz: 'val'
  121. }
  122. }
  123. }, {validate: true});
  124. },
  125. "sets the value": function() {
  126. assert(this.result);
  127. },
  128. "calls the valid callback": function() {
  129. assert.calledWith(this.valid, this.view, 'foo.bar.baz');
  130. },
  131. "is valid returns true for the specified attribute name": function () {
  132. assert(this.model.isValid('foo.bar.baz'));
  133. },
  134. "is valid returns true for the specified attribute names": function () {
  135. assert(this.model.isValid(['foo.bar.baz', 'foo.bar.baz']));
  136. },
  137. "pre validate returns no error message for the specified attribute name": function () {
  138. refute(this.model.preValidate('foo.bar.baz', 'val'));
  139. }
  140. }
  141. },
  142. "arrays": {
  143. setUp: function() {
  144. var Model = Backbone.Model.extend({
  145. validation: {
  146. 'dogs.0.name': {
  147. required: true,
  148. msg: 'error'
  149. }
  150. }
  151. });
  152. this.model = new Model();
  153. this.view = new Backbone.View({ model: this.model });
  154. Backbone.Validation.bind(this.view, {});
  155. },
  156. "invalid": {
  157. setUp: function () {
  158. this.result = this.model.set({
  159. dogs: [{ name: '' }]
  160. }, {validate: true});
  161. },
  162. "refutes setting invalid values": function() {
  163. refute(this.result);
  164. },
  165. "is valid returns false for the specified attribute name": function () {
  166. refute(this.model.isValid('dogs.0.name'));
  167. },
  168. },
  169. "valid": {
  170. setUp: function () {
  171. this.result = this.model.set({
  172. dogs: [{ name: 'good boy' }]
  173. }, {validate: true});
  174. },
  175. "sets the value": function() {
  176. assert(this.result);
  177. },
  178. "is valid returns true for the specified attribute name": function () {
  179. assert(this.model.isValid('dogs.0.name'));
  180. },
  181. }
  182. },
  183. "complex nesting": {
  184. setUp: function() {
  185. this.valid = this.spy();
  186. this.invalid = this.spy();
  187. var Model = Backbone.Model.extend({
  188. validation: {
  189. 'foo.bar.baz': {
  190. required: true,
  191. msg: 'error'
  192. },
  193. 'foo.foo': {
  194. required: true,
  195. msg: 'error'
  196. }
  197. }
  198. });
  199. this.model = new Model();
  200. this.view = new Backbone.View({model: this.model});
  201. Backbone.Validation.bind(this.view, {
  202. invalid: this.invalid,
  203. valid: this.valid
  204. });
  205. },
  206. "invalid": {
  207. setUp: function () {
  208. this.result = this.model.set({
  209. foo: {
  210. foo: '',
  211. bar: {
  212. baz: ''
  213. }
  214. }
  215. }, {validate: true});
  216. },
  217. "refutes setting invalid values": function() {
  218. refute(this.result);
  219. },
  220. "calls the invalid callback": function() {
  221. assert.calledWith(this.invalid, this.view, 'foo.bar.baz', 'error');
  222. assert.calledWith(this.invalid, this.view, 'foo.foo', 'error');
  223. },
  224. "is valid returns false for the specified attribute name": function () {
  225. refute(this.model.isValid('foo.bar.baz'));
  226. refute(this.model.isValid('foo.foo'));
  227. },
  228. "is valid returns false for the specified attribute names": function () {
  229. refute(this.model.isValid(['foo.foo', 'foo.bar.baz']));
  230. },
  231. "pre validate returns error message for the specified attribute name": function () {
  232. assert(this.model.preValidate('foo.bar.baz', ''));
  233. assert(this.model.preValidate('foo.foo', ''));
  234. }
  235. },
  236. "valid": {
  237. setUp: function () {
  238. this.result = this.model.set({
  239. foo: {
  240. foo: 'val',
  241. bar: {
  242. baz: 'val'
  243. }
  244. }
  245. }, {validate: true});
  246. },
  247. "sets the value": function() {
  248. assert(this.result);
  249. },
  250. "calls the valid callback": function() {
  251. assert.calledWith(this.valid, this.view, 'foo.bar.baz');
  252. assert.calledWith(this.valid, this.view, 'foo.foo');
  253. },
  254. "is valid returns true for the specified attribute name": function () {
  255. assert(this.model.isValid('foo.bar.baz'));
  256. assert(this.model.isValid('foo.foo'));
  257. },
  258. "is valid returns true for the specified attribute names": function () {
  259. assert(this.model.isValid(['foo.bar.baz', 'foo.foo']));
  260. },
  261. "pre validate returns no error message for the specified attribute name": function () {
  262. refute(this.model.preValidate('foo.bar.baz', 'val'));
  263. refute(this.model.preValidate('foo.foo', 'val'));
  264. }
  265. }
  266. },
  267. "complex nesting with intermediate-level validators": {
  268. setUp: function() {
  269. this.valid = this.spy();
  270. this.invalid = this.spy();
  271. var Model = Backbone.Model.extend({
  272. validation: {
  273. 'foo.bar': {
  274. fn: 'validateBazAndQux',
  275. msg: 'bazQuxError1'
  276. },
  277. 'foo.foo': {
  278. fn: 'validateBazAndQux',
  279. msg: 'bazQuxError2'
  280. }
  281. },
  282. validateBazAndQux: function (value, attr, computedState) {
  283. if (!value || !value.baz || !value.qux) {
  284. return "error";
  285. }
  286. }
  287. });
  288. this.model = new Model();
  289. this.view = new Backbone.View({model: this.model});
  290. Backbone.Validation.bind(this.view, {
  291. invalid: this.invalid,
  292. valid: this.valid
  293. });
  294. },
  295. "invalid": {
  296. setUp: function () {
  297. this.result = this.model.set({
  298. foo: {
  299. bar: {
  300. baz: '',
  301. qux: 'qux'
  302. },
  303. foo: {
  304. baz: 'baz',
  305. qux: ''
  306. }
  307. }
  308. }, {validate: true});
  309. },
  310. "refutes setting invalid values": function() {
  311. refute(this.result);
  312. },
  313. "calls the invalid callback": function() {
  314. assert.calledWith(this.invalid, this.view, 'foo.bar', 'bazQuxError1');
  315. assert.calledWith(this.invalid, this.view, 'foo.foo', 'bazQuxError2');
  316. },
  317. "isValid returns false for the specified attribute name": function () {
  318. refute(this.model.isValid('foo.bar'));
  319. refute(this.model.isValid('foo.foo'));
  320. },
  321. "isValid returns false for the specified attribute names": function () {
  322. refute(this.model.isValid(['foo.foo', 'foo.bar']));
  323. },
  324. "preValidate returns error message for the specified attribute name": function () {
  325. assert(this.model.preValidate('foo.bar', ''));
  326. assert(this.model.preValidate('foo.foo', ''));
  327. },
  328. "preValidate does not return error message if new nested values validate": function () {
  329. refute(this.model.preValidate('foo.bar', { baz: 1, qux: 1 }));
  330. refute(this.model.preValidate('foo.foo', { baz: 1, qux: 1 }));
  331. }
  332. },
  333. "valid": {
  334. setUp: function () {
  335. this.result = this.model.set({
  336. foo: {
  337. bar: {
  338. baz: 'val',
  339. qux: 'val'
  340. },
  341. foo: {
  342. baz: 'val',
  343. qux: 'val'
  344. }
  345. }
  346. }, {validate: true});
  347. },
  348. "sets the value": function() {
  349. assert(this.result);
  350. },
  351. "calls the valid callback": function() {
  352. assert.calledWith(this.valid, this.view, 'foo.bar');
  353. assert.calledWith(this.valid, this.view, 'foo.foo');
  354. },
  355. "isValid returns true for the specified attribute name": function () {
  356. assert(this.model.isValid('foo.bar'));
  357. assert(this.model.isValid('foo.foo'));
  358. },
  359. "isValid returns true for the specified attribute names": function () {
  360. assert(this.model.isValid(['foo.bar', 'foo.foo']));
  361. },
  362. "preValidate returns no error message for the specified attribute name": function () {
  363. refute(this.model.preValidate('foo.bar', { baz: 1, qux: 1 }));
  364. refute(this.model.preValidate('foo.foo', { baz: 1, qux: 1 }));
  365. },
  366. "preValidate returns error message if new nested values do not validate": function () {
  367. assert.equals(this.model.preValidate('foo.bar', { baz: '', qux: '' }), 'bazQuxError1');
  368. assert.equals(this.model.preValidate('foo.foo', { baz: '', qux: '' }), 'bazQuxError2');
  369. }
  370. }
  371. },
  372. "nested models and collections": {
  373. setUp: function () {
  374. this.valid = this.spy();
  375. this.invalid = this.spy();
  376. var Model = Backbone.Model.extend({
  377. });
  378. var Collection = Backbone.Collection.extend({
  379. model: Model
  380. });
  381. this.model = new Model();
  382. this.model.set({
  383. model: this.model,
  384. collection: new Collection([this.model])
  385. });
  386. this.view = new Backbone.View({model: this.model});
  387. Backbone.Validation.bind(this.view, {
  388. invalid: this.invalid,
  389. valid: this.valid
  390. });
  391. this.result = this.model.set({
  392. foo: 'bar'
  393. }, {validate: true});
  394. },
  395. "are ignored": function() {
  396. assert(this.result);
  397. }
  398. }
  399. });