data-parser.spec.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. import {expect} from 'chai';
  2. import {DataType} from './data-type.js';
  3. import {format} from '@e22m4u/js-format';
  4. import {DataParser} from './data-parser.js';
  5. import {DataSchemaRegistry} from './data-schema-registry.js';
  6. import {
  7. arrayTypeParser,
  8. numberTypeParser,
  9. objectTypeParser,
  10. stringTypeParser,
  11. booleanTypeParser,
  12. } from './data-parsers/index.js';
  13. describe('DataParser', function () {
  14. describe('getParsers', function () {
  15. it('should return a default parser list', function () {
  16. const S = new DataParser();
  17. const res = S.getParsers();
  18. expect(res).to.be.eql([
  19. stringTypeParser,
  20. booleanTypeParser,
  21. numberTypeParser,
  22. arrayTypeParser,
  23. objectTypeParser,
  24. ]);
  25. });
  26. it('should return a modified parser list', function () {
  27. const S = new DataParser();
  28. const parser1 = () => undefined;
  29. const parser2 = () => undefined;
  30. S.setParsers([parser1, parser2]);
  31. const res = S.getParsers();
  32. expect(res).to.be.eql([parser1, parser2]);
  33. });
  34. });
  35. describe('setParsers', function () {
  36. it('should require a given value to be an array', function () {
  37. const S = new DataParser();
  38. const throwable = v => () => S.setParsers(v);
  39. const error = s =>
  40. format('Data parsers must be an Array, but %s was given.', s);
  41. expect(throwable('str')).to.throw(error('"str"'));
  42. expect(throwable('')).to.throw(error('""'));
  43. expect(throwable(10)).to.throw(error('10'));
  44. expect(throwable(0)).to.throw(error('0'));
  45. expect(throwable(true)).to.throw(error('true'));
  46. expect(throwable(false)).to.throw(error('false'));
  47. expect(throwable({})).to.throw(error('Object'));
  48. expect(throwable(null)).to.throw(error('null'));
  49. expect(throwable(undefined)).to.throw(error('undefined'));
  50. throwable([])();
  51. });
  52. it('should require given parsers to be a function', function () {
  53. const S = new DataParser();
  54. const throwable = v => () => S.setParsers([v]);
  55. const error = s =>
  56. format('Data parser must be a Function, but %s was given.', s);
  57. expect(throwable('str')).to.throw(error('"str"'));
  58. expect(throwable('')).to.throw(error('""'));
  59. expect(throwable(10)).to.throw(error('10'));
  60. expect(throwable(0)).to.throw(error('0'));
  61. expect(throwable(true)).to.throw(error('true'));
  62. expect(throwable(false)).to.throw(error('false'));
  63. expect(throwable([])).to.throw(error('Array'));
  64. expect(throwable({})).to.throw(error('Object'));
  65. expect(throwable(null)).to.throw(error('null'));
  66. expect(throwable(undefined)).to.throw(error('undefined'));
  67. throwable(() => undefined)();
  68. });
  69. it('should set the parsers list', function () {
  70. const S = new DataParser();
  71. const parser1 = () => undefined;
  72. const parser2 = () => undefined;
  73. S.setParsers([parser1, parser2]);
  74. const res1 = S.getParsers();
  75. expect(res1).to.be.eql([parser1, parser2]);
  76. });
  77. it('should able to clean the parser list', function () {
  78. const S = new DataParser();
  79. const parser1 = () => undefined;
  80. const parser2 = () => undefined;
  81. S.setParsers([parser1, parser2]);
  82. const res1 = S.getParsers();
  83. expect(res1).to.be.eql([parser1, parser2]);
  84. S.setParsers([]);
  85. const res2 = S.getParsers();
  86. expect(res2).to.be.eql([]);
  87. });
  88. });
  89. describe('defineSchema', function () {
  90. it('should pass a given schema definition to the registry', function () {
  91. const S = new DataParser();
  92. const registry = S.getService(DataSchemaRegistry);
  93. const schemaDef = {name: 'mySchema', schema: {}};
  94. S.defineSchema(schemaDef);
  95. const res = registry.getDefinition(schemaDef.name);
  96. expect(res).to.be.eql(schemaDef);
  97. });
  98. it('should return a current instance', function () {
  99. const S = new DataParser();
  100. const schemaDef = {name: 'mySchema', schema: {}};
  101. const res = S.defineSchema(schemaDef);
  102. expect(res).to.be.eq(S);
  103. });
  104. });
  105. describe('hasSchema', function () {
  106. it('should return true if a given name is registered', function () {
  107. const S = new DataParser();
  108. const schemaDef = {name: 'mySchema', schema: {}};
  109. expect(S.hasSchema(schemaDef.name)).to.be.false;
  110. S.defineSchema(schemaDef);
  111. expect(S.hasSchema(schemaDef.name)).to.be.true;
  112. });
  113. });
  114. describe('getSchema', function () {
  115. it('should return a register schema for a given name', function () {
  116. const S = new DataParser();
  117. const schemaDef = {name: 'mySchema', schema: {}};
  118. S.defineSchema(schemaDef);
  119. const res = S.getSchema(schemaDef.name);
  120. expect(res).to.be.eql(schemaDef.schema);
  121. });
  122. it('should throw an error if a given name is not registered', function () {
  123. const S = new DataParser();
  124. const throwable = () => S.getSchema('mySchema');
  125. expect(throwable).to.throw('Data schema "mySchema" is not found.');
  126. });
  127. });
  128. describe('parse', function () {
  129. it('should require the "options" argument to be an object', function () {
  130. const S = new DataParser();
  131. const throwable = v => () => S.parse(10, {}, v);
  132. const error = s =>
  133. format('Parsing options must be an Object, but %s was given.', s);
  134. expect(throwable('str')).to.throw(error('"str"'));
  135. expect(throwable('')).to.throw(error('""'));
  136. expect(throwable(10)).to.throw(error('10'));
  137. expect(throwable(0)).to.throw(error('0'));
  138. expect(throwable(true)).to.throw(error('true'));
  139. expect(throwable(false)).to.throw(error('false'));
  140. expect(throwable([])).to.throw(error('Array'));
  141. expect(throwable(null)).to.throw(error('null'));
  142. expect(throwable(() => undefined)).to.throw(error('Function'));
  143. throwable({})();
  144. throwable(undefined)();
  145. });
  146. it('should require the "sourcePath" argument to be a non-empty string', function () {
  147. const S = new DataParser();
  148. const throwable = v => () => S.parse(10, {}, {sourcePath: v});
  149. const error = s =>
  150. format(
  151. 'Option "sourcePath" must be a non-empty String, but %s was given.',
  152. s,
  153. );
  154. expect(throwable('')).to.throw(error('""'));
  155. expect(throwable(10)).to.throw(error('10'));
  156. expect(throwable(0)).to.throw(error('0'));
  157. expect(throwable(true)).to.throw(error('true'));
  158. expect(throwable(false)).to.throw(error('false'));
  159. expect(throwable([])).to.throw(error('Array'));
  160. expect(throwable({})).to.throw(error('Object'));
  161. expect(throwable(null)).to.throw(error('null'));
  162. expect(throwable(() => undefined)).to.throw(error('Function'));
  163. throwable('str')();
  164. throwable(undefined)();
  165. });
  166. it('should require the "shallowMode" argument to be a boolean', function () {
  167. const S = new DataParser();
  168. const throwable = v => () => S.parse(10, {}, {shallowMode: v});
  169. const error = s =>
  170. format('Option "shallowMode" must be a Boolean, but %s was given.', s);
  171. expect(throwable('str')).to.throw(error('"str"'));
  172. expect(throwable('')).to.throw(error('""'));
  173. expect(throwable(10)).to.throw(error('10'));
  174. expect(throwable(0)).to.throw(error('0'));
  175. expect(throwable([])).to.throw(error('Array'));
  176. expect(throwable({})).to.throw(error('Object'));
  177. expect(throwable(null)).to.throw(error('null'));
  178. expect(throwable(() => undefined)).to.throw(error('Function'));
  179. throwable(true)();
  180. throwable(false)();
  181. throwable(undefined)();
  182. });
  183. it('should require the "noParsingErrors" argument to be a boolean', function () {
  184. const S = new DataParser();
  185. const throwable = v => () => S.parse(10, {}, {noParsingErrors: v});
  186. const error = s =>
  187. format(
  188. 'Option "noParsingErrors" must be a Boolean, but %s was given.',
  189. s,
  190. );
  191. expect(throwable('str')).to.throw(error('"str"'));
  192. expect(throwable('')).to.throw(error('""'));
  193. expect(throwable(10)).to.throw(error('10'));
  194. expect(throwable(0)).to.throw(error('0'));
  195. expect(throwable([])).to.throw(error('Array'));
  196. expect(throwable({})).to.throw(error('Object'));
  197. expect(throwable(null)).to.throw(error('null'));
  198. expect(throwable(() => undefined)).to.throw(error('Function'));
  199. throwable(true)();
  200. throwable(false)();
  201. throwable(undefined)();
  202. });
  203. it('should validate a given schema in the shallow mode', function () {
  204. const S = new DataParser();
  205. const throwable = () => S.parse(10, {required: 10});
  206. expect(throwable).to.throw(
  207. 'Schema option "required" must be a Boolean, but 10 was given.',
  208. );
  209. S.parse([], {type: DataType.ARRAY, items: {type: 10}});
  210. });
  211. it('should resolve the data schema from a given factory', function () {
  212. const S = new DataParser();
  213. S.setParsers([stringTypeParser]);
  214. const res = S.parse(10, () => ({type: DataType.STRING}));
  215. expect(res).to.be.eq('10');
  216. });
  217. it('should resolve the data schema from a schema name', function () {
  218. const S = new DataParser();
  219. S.setParsers([stringTypeParser]);
  220. S.getService(DataSchemaRegistry).defineSchema({
  221. name: 'mySchema',
  222. schema: {type: DataType.STRING},
  223. });
  224. const res = S.parse(10, 'mySchema');
  225. expect(res).to.be.eq('10');
  226. });
  227. it('should resolve a schema name from a given factory', function () {
  228. const S = new DataParser();
  229. S.setParsers([stringTypeParser]);
  230. S.getService(DataSchemaRegistry).defineSchema({
  231. name: 'mySchema',
  232. schema: {type: DataType.STRING},
  233. });
  234. const res = S.parse(10, () => 'mySchema');
  235. expect(res).to.be.eq('10');
  236. });
  237. it('should resolve a schema factory from a named schema', function () {
  238. const S = new DataParser();
  239. S.setParsers([stringTypeParser]);
  240. S.getService(DataSchemaRegistry).defineSchema({
  241. name: 'mySchema',
  242. schema: () => ({type: DataType.STRING}),
  243. });
  244. const res = S.parse(10, 'mySchema');
  245. expect(res).to.be.eq('10');
  246. });
  247. it('should pass specific arguments to data parsers', function () {
  248. const S = new DataParser();
  249. const value = 10;
  250. const schema = {type: DataType.NUMBER};
  251. const options = {sourcePath: 'mySource'};
  252. let invoked = 0;
  253. const parser = (...args) => {
  254. invoked++;
  255. expect(args).to.be.eql([value, schema, options, S.container]);
  256. return args[0];
  257. };
  258. S.setParsers([parser]);
  259. const res = S.parse(value, schema, options);
  260. expect(res).to.be.eq(value);
  261. expect(invoked).to.be.eq(1);
  262. });
  263. it('should propagate an error from the data parser', function () {
  264. const S = new DataParser();
  265. const parser = () => {
  266. throw new Error('Caught!');
  267. };
  268. S.setParsers([parser]);
  269. const throwable = () => S.parse(10, {});
  270. expect(throwable).to.throw('Caught!');
  271. });
  272. it('should apply parsers sequentially to a given value', function () {
  273. const S = new DataParser();
  274. const value = 'a';
  275. S.setParsers([v => v + 'b', v => v + 'c']);
  276. const res = S.parse(value, {});
  277. expect(res).to.be.eq('abc');
  278. });
  279. it('should not parse array items in the shallow mode even if the items schema is provided', function () {
  280. const S = new DataParser();
  281. const value = [1, 2, 3];
  282. const schema = {
  283. type: DataType.ARRAY,
  284. items: {type: DataType.STRING},
  285. };
  286. S.setParsers([stringTypeParser]);
  287. const res = S.parse(value, schema, {shallowMode: true});
  288. expect(res).to.be.eql(value);
  289. });
  290. it('should not parse array items when the items schema is not provided', function () {
  291. const S = new DataParser();
  292. const value = [1, 2, 3];
  293. const schema = {type: DataType.ARRAY};
  294. let invoked = 0;
  295. const parser = (...args) => {
  296. invoked++;
  297. expect(args[0]).to.be.eql(value);
  298. return args[0];
  299. };
  300. S.setParsers([parser]);
  301. const res = S.parse(value, schema);
  302. expect(res).to.be.eql(value);
  303. expect(invoked).to.be.eq(1);
  304. });
  305. it('should parse array items when the array schema is provided', function () {
  306. const S = new DataParser();
  307. const value = [1, 2, 3];
  308. const schema = {
  309. type: DataType.ARRAY,
  310. items: {type: DataType.STRING},
  311. };
  312. const expectedCalls = [
  313. [value, schema, undefined, S.container],
  314. [1, schema.items, {sourcePath: 'array[0]'}, S.container],
  315. [2, schema.items, {sourcePath: 'array[1]'}, S.container],
  316. [3, schema.items, {sourcePath: 'array[2]'}, S.container],
  317. ];
  318. const calls = [];
  319. const parser = (...args) => {
  320. calls.push(args);
  321. return Array.isArray(args[0]) ? args[0] : String(args[0]);
  322. };
  323. S.setParsers([parser]);
  324. const res = S.parse(value, schema);
  325. expect(res).to.be.eql(['1', '2', '3']);
  326. expect(expectedCalls).to.be.eql(calls);
  327. });
  328. it('should add an array index to a provided source path', function () {
  329. const S = new DataParser();
  330. const value = [1, 2, 3];
  331. const schema = {
  332. type: DataType.ARRAY,
  333. items: {type: DataType.STRING},
  334. };
  335. const options = {sourcePath: 'mySource'};
  336. const expectedCalls = [
  337. [value, schema, options, S.container],
  338. [1, schema.items, {sourcePath: 'mySource[0]'}, S.container],
  339. [2, schema.items, {sourcePath: 'mySource[1]'}, S.container],
  340. [3, schema.items, {sourcePath: 'mySource[2]'}, S.container],
  341. ];
  342. const calls = [];
  343. const parser = (...args) => {
  344. calls.push(args);
  345. return Array.isArray(args[0]) ? args[0] : String(args[0]);
  346. };
  347. S.setParsers([parser]);
  348. const res = S.parse(value, schema, options);
  349. expect(res).to.be.eql(['1', '2', '3']);
  350. expect(expectedCalls).to.be.eql(calls);
  351. });
  352. it('should resolve a schema factory from the "items" option', function () {
  353. const S = new DataParser();
  354. S.setParsers([stringTypeParser]);
  355. const factory = () => ({type: DataType.STRING});
  356. const schema = {type: DataType.ARRAY, items: factory};
  357. const res = S.parse([10], schema);
  358. expect(res).to.be.eql(['10']);
  359. });
  360. it('should resolve a schema name from the "items" option', function () {
  361. const S = new DataParser();
  362. S.setParsers([stringTypeParser]);
  363. const schemaA = {
  364. type: DataType.ARRAY,
  365. items: 'schemaB',
  366. };
  367. S.getService(DataSchemaRegistry).defineSchema({
  368. name: 'schemaB',
  369. schema: {type: DataType.STRING},
  370. });
  371. const res = S.parse([10], schemaA);
  372. expect(res).to.be.eql(['10']);
  373. });
  374. it('should not parse object properties in the shallow mode even if the properties schema is provided', function () {
  375. const S = new DataParser();
  376. const value = {p1: 1, p2: 2, p3: 3};
  377. const schema = {
  378. type: DataType.OBJECT,
  379. properties: {
  380. p1: {type: DataType.STRING},
  381. p2: {type: DataType.STRING},
  382. p3: {type: DataType.STRING},
  383. },
  384. };
  385. S.setParsers([stringTypeParser]);
  386. const res = S.parse(value, schema, {shallowMode: true});
  387. expect(res).to.be.eql(value);
  388. });
  389. it('should not parse object properties when the properties schema is not provided', function () {
  390. const S = new DataParser();
  391. const value = {p1: 1, p2: 2, p3: 3};
  392. const schema = {type: DataType.OBJECT};
  393. let invoked = 0;
  394. const parser = (...args) => {
  395. invoked++;
  396. expect(args).to.be.eql([value, schema, undefined, S.container]);
  397. return args[0];
  398. };
  399. S.setParsers([parser]);
  400. const res = S.parse(value, schema);
  401. expect(res).to.be.eql(value);
  402. expect(invoked).to.be.eq(1);
  403. });
  404. it('should parse object properties when the properties schema is provided', function () {
  405. const S = new DataParser();
  406. const value = {p1: 1, p2: 2, p3: 3};
  407. const schema = {
  408. type: DataType.OBJECT,
  409. properties: {
  410. p1: {type: DataType.STRING},
  411. p2: {type: DataType.STRING},
  412. p3: {type: DataType.STRING},
  413. },
  414. };
  415. const expectedCalls = [
  416. [value, schema, undefined, S.container],
  417. [1, schema.properties.p1, {sourcePath: 'p1'}, S.container],
  418. [2, schema.properties.p2, {sourcePath: 'p2'}, S.container],
  419. [3, schema.properties.p3, {sourcePath: 'p3'}, S.container],
  420. ];
  421. const calls = [];
  422. const parser = (...args) => {
  423. calls.push(args);
  424. return typeof args[0] === 'object' ? args[0] : String(args[0]);
  425. };
  426. S.setParsers([parser]);
  427. const res = S.parse(value, schema);
  428. expect(res).to.be.eql({p1: '1', p2: '2', p3: '3'});
  429. expect(expectedCalls).to.be.eql(calls);
  430. });
  431. it('should apply parsers sequentially to a given object and its properties', function () {
  432. const S = new DataParser();
  433. const value = {p1: 'a', p2: 'b', p3: 'c'};
  434. const schema = {
  435. type: DataType.OBJECT,
  436. properties: {
  437. p1: {type: DataType.STRING},
  438. p2: {type: DataType.STRING},
  439. p3: {type: DataType.STRING},
  440. },
  441. };
  442. const parser = suffix => value => {
  443. return typeof value === 'string' ? value + suffix : value;
  444. };
  445. S.setParsers([parser('b'), parser('c')]);
  446. const res = S.parse(value, schema);
  447. expect(res).to.be.eql({p1: 'abc', p2: 'bbc', p3: 'cbc'});
  448. });
  449. it('should not parse object properties without a specified schema', function () {
  450. const S = new DataParser();
  451. const value = {p1: 1, p2: 2, p3: 3};
  452. const schema = {
  453. type: DataType.OBJECT,
  454. properties: {
  455. p1: {type: DataType.NUMBER},
  456. },
  457. };
  458. const expectedCalls = [
  459. [value, schema, undefined, S.container],
  460. [value.p1, schema.properties.p1, {sourcePath: 'p1'}, S.container],
  461. ];
  462. const calls = [];
  463. const parser = (...args) => {
  464. calls.push(args);
  465. return args[0];
  466. };
  467. S.setParsers([parser]);
  468. const res = S.parse(value, schema);
  469. expect(res).to.be.eql(value);
  470. expect(expectedCalls).to.be.eql(calls);
  471. });
  472. it('should add property name to a provided source path', function () {
  473. const S = new DataParser();
  474. const value = {p1: 1, p2: 2, p3: 3};
  475. const schema = {
  476. type: DataType.OBJECT,
  477. properties: {
  478. p1: {type: DataType.STRING},
  479. p2: {type: DataType.STRING},
  480. p3: {type: DataType.STRING},
  481. },
  482. };
  483. const options = {sourcePath: 'mySource'};
  484. const expectedCalls = [
  485. [value, schema, options, S.container],
  486. [1, schema.properties.p1, {sourcePath: 'mySource.p1'}, S.container],
  487. [2, schema.properties.p2, {sourcePath: 'mySource.p2'}, S.container],
  488. [3, schema.properties.p3, {sourcePath: 'mySource.p3'}, S.container],
  489. ];
  490. const calls = [];
  491. const parser = (...args) => {
  492. calls.push(args);
  493. return typeof args[0] === 'object' ? args[0] : String(args[0]);
  494. };
  495. S.setParsers([parser]);
  496. const res = S.parse(value, schema, options);
  497. expect(res).to.be.eql({p1: '1', p2: '2', p3: '3'});
  498. expect(expectedCalls).to.be.eql(calls);
  499. });
  500. it('should resolve a schema factory from the "properties" option', function () {
  501. const S = new DataParser();
  502. S.setParsers([stringTypeParser]);
  503. const factory = () => ({
  504. type: DataType.OBJECT,
  505. properties: {
  506. prop: {type: DataType.STRING},
  507. },
  508. });
  509. const schema = {
  510. type: DataType.OBJECT,
  511. properties: factory,
  512. };
  513. const res = S.parse({prop: 10}, schema);
  514. expect(res).to.be.eql({prop: '10'});
  515. });
  516. it('should resolve a schema name from the "properties" option', function () {
  517. const S = new DataParser();
  518. S.setParsers([stringTypeParser]);
  519. const schemaA = {
  520. type: DataType.OBJECT,
  521. properties: 'schemaB',
  522. };
  523. S.getService(DataSchemaRegistry).defineSchema({
  524. name: 'schemaB',
  525. schema: {
  526. type: DataType.OBJECT,
  527. properties: {
  528. prop: {type: DataType.STRING},
  529. },
  530. },
  531. });
  532. const res = S.parse({prop: 10}, schemaA);
  533. expect(res).to.be.eql({prop: '10'});
  534. });
  535. it('should throw an error if a properties schema from the schema factory is a non-array schema', function () {
  536. const S = new DataParser();
  537. const factory = () => ({type: DataType.BOOLEAN});
  538. const schema = {
  539. type: DataType.OBJECT,
  540. properties: factory,
  541. };
  542. const throwable = () => S.parse({prop: 10}, schema);
  543. expect(throwable).to.throw(
  544. 'Unable to get the "properties" option ' +
  545. 'from the data schema of "boolean" type.',
  546. );
  547. });
  548. it('should throw an error if a properties schema from the schema name is a non-array schema', function () {
  549. const S = new DataParser();
  550. const schemaA = {
  551. type: DataType.OBJECT,
  552. properties: 'schemaB',
  553. };
  554. S.getService(DataSchemaRegistry).defineSchema({
  555. name: 'schemaB',
  556. schema: {type: DataType.BOOLEAN},
  557. });
  558. const throwable = () => S.parse({prop: 10}, schemaA);
  559. expect(throwable).to.throw(
  560. 'Unable to get the "properties" option ' +
  561. 'from the data schema of "boolean" type.',
  562. );
  563. });
  564. it('should resolve a schema factory from the property schema', function () {
  565. const S = new DataParser();
  566. S.setParsers([stringTypeParser]);
  567. const factory = () => ({type: DataType.STRING});
  568. const schema = {
  569. type: DataType.OBJECT,
  570. properties: {prop: factory},
  571. };
  572. const res = S.parse({prop: 10}, schema);
  573. expect(res).to.be.eql({prop: '10'});
  574. });
  575. it('should resolve a schema name from the property schema', function () {
  576. const S = new DataParser();
  577. S.setParsers([stringTypeParser]);
  578. const schemaA = {
  579. type: DataType.OBJECT,
  580. properties: {prop: 'schemaB'},
  581. };
  582. S.getService(DataSchemaRegistry).defineSchema({
  583. name: 'schemaB',
  584. schema: {type: DataType.STRING},
  585. });
  586. const res = S.parse({prop: 10}, schemaA);
  587. expect(res).to.be.eql({prop: '10'});
  588. });
  589. it('should not set undefined value to a non existent property', function () {
  590. const S = new DataParser();
  591. const parser = value => value;
  592. S.setParsers([parser]);
  593. const value = {p1: 'str'};
  594. const schema = {
  595. type: DataType.OBJECT,
  596. properties: {
  597. p1: {type: DataType.ANY},
  598. p2: {type: DataType.ANY},
  599. },
  600. };
  601. const res = S.parse(value, schema);
  602. expect(res).to.be.eql(value);
  603. });
  604. });
  605. });