Home Reference Source

src/Model/itemsModel.test.js

  1. import {Model} from "./index";
  2. import {default as deepEqual} from "deep-equal";
  3. import {
  4. stringsCollection,
  5. stringsMinMaxCollection,
  6. objectCollection, objectCollectionDefaults
  7. } from "../../fixtures/ItemsModel.schemas";
  8. import {BaseModel} from "./base-model";
  9. import {basicCollection} from "../../fixtures/PropertiesModel.schemas";
  10.  
  11. describe("ItemsModel Class", function () {
  12.  
  13. describe("Simple ItemsModel Tests", () => {
  14.  
  15. describe("LifeCycle: Instantiation", () => {
  16. let _owner;
  17. beforeEach(() => {
  18. _owner = new Model({schemas: [stringsCollection]});
  19. });
  20.  
  21. it("should initialize a schema and a schema object", () => {
  22. expect(_owner.model.$model).toBeDefined();
  23. expect(_owner.model.$model instanceof BaseModel).toBe(true);
  24. });
  25.  
  26. it("should not initialize a invalid schema and schema object", () => {
  27. let badSchema = Object.assign({}, stringsCollection, {
  28. items: [{type: "INVALID"}],
  29. });
  30. expect(() => new Model({schemas: [badSchema]})).toThrow();
  31. });
  32. });
  33.  
  34. describe("ItemsModel LifeCycle: Creation", () => {
  35. let _d, _owner;
  36.  
  37. beforeEach(() => {
  38. _owner = new Model({schemas: [stringsCollection]});
  39. });
  40.  
  41. it("should populate with valid data and make that data accessible", (done) => {
  42. _d = ["abc", "def", "ghi"];
  43. let _cnt = 0;
  44. _owner.subscribe({
  45. next: (m) => {
  46. _cnt++;
  47. expect(deepEqual(_owner.model, _d)).toBe(true);
  48. },
  49. error: done,
  50. });
  51.  
  52. setTimeout(() => {
  53. expect(_cnt).toEqual(1);
  54. done();
  55. }, 100);
  56.  
  57. _owner.model = _d;
  58. });
  59.  
  60. it("should reject invalid data and leave model pristine", () => {
  61. _d = [99, 100, 101];
  62.  
  63. _owner.model = _d;
  64. expect(_owner.model.length).toEqual(0);
  65. });
  66. });
  67. });
  68.  
  69. describe("Nested Elements Tests", () => {
  70.  
  71. describe("LifeCycle: Instantiation", () => {
  72. let _owner;
  73. beforeEach(() => {
  74. _owner = new Model({schemas: [objectCollection]});
  75. });
  76.  
  77. it("should initialize a valid schema and a schema object", () => {
  78. expect(_owner.model.$model).toBeDefined();
  79. expect(_owner.model.$model instanceof BaseModel).toBe(true);
  80. expect(_owner.model.$model).toBeDefined();
  81. expect(_owner.model.$model instanceof BaseModel).toBe(true);
  82. });
  83. });
  84.  
  85. describe("ItemsModel LifeCycle: Nested Create", () => {
  86. let _d, _owner;
  87. beforeEach(() => {
  88. _owner = new Model({schemas: [objectCollection]});
  89. });
  90.  
  91. it("should populate with valid data and make that data accessible", (done) => {
  92. _d = [{
  93. name: "Item A",
  94. value: 1,
  95. }, {
  96. name: "Item B",
  97. }, {
  98. name: "Item C",
  99. value: 2,
  100. }];
  101.  
  102. let _cnt = 0;
  103.  
  104. _owner.subscribe({
  105. next: (m) => {
  106. _cnt++;
  107. },
  108. error: done,
  109. });
  110.  
  111. setTimeout(() => {
  112. expect(_cnt).toEqual(1);
  113. done();
  114. }, 100);
  115.  
  116. _owner.model = _d;
  117. // expect(deepEqual(_owner.model, _d)).toBe(true);
  118. });
  119.  
  120. it("should reject invalid data and leave model pristine", () => {
  121. _d = [{
  122. name: 123,
  123. value: 1,
  124. }, {
  125. value: "Item B",
  126. }, {
  127. value: 2,
  128. }];
  129.  
  130. _owner.model = _d;
  131. expect(typeof _owner.errors).toBe("object");
  132. expect(deepEqual(_owner.model, [])).toBe(true);
  133. });
  134. });
  135.  
  136. describe("LifeCycle: Update", () => {
  137.  
  138. let _d, _owner;
  139. beforeEach(() => {
  140. _owner = new Model({schemas: [objectCollection]});
  141. });
  142.  
  143. it("should update nested models with valid data and pass validation", () => {
  144. _d = [{
  145. name: "Item A",
  146. value: 1,
  147. }, {
  148. name: "Item B",
  149. }, {
  150. name: "Item C",
  151. value: 2,
  152. }];
  153.  
  154. _owner.model = _d;
  155.  
  156. _owner.model[1] = {
  157. name: "Item B",
  158. value: 3
  159. };
  160.  
  161. expect(_owner.errors).toBe(null);
  162. expect(_owner.model[1]).toEqual({name: "Item B", value: 3});
  163. });
  164.  
  165. it("should updated properties in nested objects with valid data and pass validation", () => {
  166. _d = [{
  167. name: "Item A",
  168. value: 1,
  169. }, {
  170. name: "Item B",
  171. }, {
  172. name: "Item C",
  173. value: 2,
  174. }];
  175.  
  176. _owner.model = _d;
  177.  
  178. _owner.model[1].value = 3;
  179.  
  180.  
  181. expect(_owner.errors).toBe(null);
  182. expect(_owner.model[1]).toEqual({name: "Item B", value: 3});
  183. });
  184. });
  185.  
  186. describe("LifeCycle: Delete", () => {
  187. let _owner;
  188. beforeEach(() => {
  189. _owner = new Model({schemas: [stringsCollection]});
  190. });
  191.  
  192. let _d = ["Item A", "Item B", "Item C"];
  193.  
  194. it("should allow deletion of nested properties that are not required", () => {
  195. _owner.model = _d;
  196. delete _owner.model[1];
  197. expect(_owner.errors).toBe(null);
  198. expect(_owner.model.length).toBe(2);
  199. });
  200.  
  201. it("should prevent deletion of nested properties that are required", () => {
  202. _owner.model = _d;
  203. delete _owner.model[0];
  204. delete _owner.model[1];
  205. delete _owner.model[2];
  206. expect(typeof _owner.errors).toBe("object");
  207. expect(_owner.model.length).toBe(1);
  208. });
  209. });
  210.  
  211. describe("LifeCycle: Reset", () => {
  212. let _owner;
  213. beforeEach(() => {
  214. _owner = new Model({schemas: [objectCollection]});
  215. });
  216.  
  217. it("should notify subsequent validations", (done) => {
  218. const _d = [{
  219. name: "Item A",
  220. value: 1,
  221. }, {
  222. name: "Item B",
  223. }, {
  224. name: "Item C",
  225. value: 2,
  226. }];
  227.  
  228. _owner.model = _d;
  229.  
  230. setTimeout(() => {
  231. _owner.subscribe({
  232. next: (m) => {
  233. expect(m.model.length).toEqual(3);
  234. done()
  235. },
  236. error: done,
  237. });
  238.  
  239. _owner.model = [{
  240. name: "Item D",
  241. value: 1,
  242. }, {
  243. name: "Item E",
  244. value: 2,
  245. }, {
  246. name: "Item F",
  247. value: 3,
  248. }];
  249. }, 100);
  250. });
  251. });
  252.  
  253.  
  254. });
  255.  
  256. describe("Array Prototype method tests", () => {
  257. let _owner;
  258. beforeEach(() => {
  259. _owner = new Model({schemas: [stringsMinMaxCollection]});
  260. _owner.model = ["Item A", "Item B", "Item C"];
  261. });
  262.  
  263. it("should fill with validation", () => {
  264. _owner.model.fill(["Item A", "Item B", "Item C", "Item D"]);
  265. expect(typeof _owner.errors).toBe("object");
  266. expect(_owner.model.length).toBe(3);
  267. });
  268.  
  269. it("should pop with validation", () => {
  270. _owner.model.pop();
  271. _owner.model.pop();
  272. _owner.model.pop();
  273. expect(typeof _owner.errors).toBe("object");
  274. expect(_owner.model.length).toBe(1);
  275. });
  276.  
  277. it("should push with validation", () => {
  278. _owner.model.push("Item D");
  279. expect(typeof _owner.errors).toBe("object");
  280. expect(_owner.model.length).toBe(3);
  281. expect(_owner.model[2]).toBe("Item C");
  282. });
  283.  
  284. it("should shift with validation", () => {
  285. _owner.model.shift();
  286. _owner.model.shift();
  287. _owner.model.shift();
  288. expect(typeof _owner.errors).toBe("object");
  289. expect(_owner.model.length).toBe(1);
  290. });
  291.  
  292. it("should splice with validation", () => {
  293. // remove all..
  294. _owner.model.splice(0, -1);
  295. expect(typeof _owner.errors).toBe("object");
  296. expect(_owner.model.length).toBe(3);
  297. // append element...
  298. _owner.model.splice(0, 0, "Item D");
  299. expect(typeof _owner.errors).toBe("object");
  300. expect(_owner.model.length).toBe(3);
  301. });
  302.  
  303. it("should unshift with validation", () => {
  304. _owner.model.unshift("Item Z");
  305. expect(typeof _owner.errors).toBe("object");
  306. expect(_owner.model.length).toBe(3);
  307. });
  308. });
  309.  
  310. describe("Default Values", () => {
  311. it("should apply defaults to items", () => {
  312. const _owner = new Model({schemas: [objectCollectionDefaults]}, {ajvOptions: {useDefaults: true}});
  313. _owner.model = [{}];
  314. expect(_owner.model[0]).toEqual({name: "abc"});
  315. });
  316. });
  317.  
  318. describe("Model Class methods ", () => {
  319. let _owner;
  320.  
  321. it("should not reset if it would invalidate model", () => {
  322. _owner = new Model({schemas: [stringsMinMaxCollection]});
  323. _owner.model = ["Item A", "Item B", "Item C"];
  324. expect(_owner.model.length).toBe(3);
  325. _owner.model.$model.reset();
  326. expect(_owner.model.length).toBe(3);
  327. });
  328.  
  329. it("should reset its collection if allowed", () => {
  330. _owner = new Model({schemas: [stringsCollection]});
  331. _owner.model = ["Item A", "Item B", "Item C"];
  332. expect(_owner.model.length).toBe(3);
  333. _owner.model.$model.reset();
  334. expect(_owner.model.length).toBe(0);
  335. });
  336.  
  337. it("should quietly validate data with the validate method", () => {
  338. _owner = new Model({schemas: [stringsCollection]});
  339. expect(_owner.model.$model.validate([1, 2, 3])).toBe("data/0 must be string");
  340. expect(_owner.model.$model.validate(["1", "2", "3"])).toBe(true);
  341. });
  342.  
  343. it("should freeze its model", () => {
  344. _owner = new Model({schemas: [stringsCollection]});
  345. _owner.model = ["Item A", "Item B", "Item C"];
  346. _owner.model.$model.freeze();
  347. expect(_owner.model.$model.isFrozen).toBe(true);
  348. _owner.model = ["1", "2", "3"];
  349. expect(deepEqual(_owner.model, ["Item A", "Item B", "Item C"])).toBe(true);
  350. });
  351.  
  352. it("should freeze its model hierarchy", () => {
  353. const _orig = [{
  354. name: "My Name",
  355. active: true,
  356. }];
  357. _owner = new Model({schemas: [basicCollection]});
  358. _owner.model = _orig;
  359. _owner.model.$model.freeze();
  360.  
  361. expect(() => _owner.model[0].name = "Other Name")
  362. .toThrow("model path \"root#/items\" is non-configurable and non-writable");
  363. });
  364. });
  365. });