references-many-resolver.spec.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. import {expect} from 'chai';
  2. import {format} from '@e22m4u/js-format';
  3. import {DatabaseSchema} from '../database-schema.js';
  4. import {ReferencesManyResolver} from './references-many-resolver.js';
  5. import {
  6. DataType,
  7. RelationType,
  8. DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK,
  9. } from '../definition/index.js';
  10. describe('ReferencesManyResolver', function () {
  11. describe('includeTo', function () {
  12. it('requires the "entities" parameter to be an array', async function () {
  13. const dbs = new DatabaseSchema();
  14. const R = dbs.getService(ReferencesManyResolver);
  15. const error = v =>
  16. format(
  17. 'The parameter "entities" of ReferencesManyResolver.includeTo requires ' +
  18. 'an Array of Object, but %s was given.',
  19. v,
  20. );
  21. const throwable = v =>
  22. R.includeTo(v, 'sourceName', 'targetName', 'relationName');
  23. await expect(throwable('')).to.be.rejectedWith(error('""'));
  24. await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
  25. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  26. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  27. await expect(throwable(false)).to.be.rejectedWith(error('false'));
  28. await expect(throwable({})).to.be.rejectedWith(error('Object'));
  29. await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
  30. await expect(throwable(null)).to.be.rejectedWith(error('null'));
  31. });
  32. it('requires elements of the "entities" parameter to be an Object', async function () {
  33. const dbs = new DatabaseSchema();
  34. const R = dbs.getService(ReferencesManyResolver);
  35. const error = v =>
  36. format(
  37. 'The parameter "entities" of ReferencesManyResolver.includeTo requires ' +
  38. 'an Array of Object, but %s was given.',
  39. v,
  40. );
  41. const throwable = v =>
  42. R.includeTo([v], 'sourceName', 'targetName', 'relationName');
  43. await expect(throwable('')).to.be.rejectedWith(error('""'));
  44. await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
  45. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  46. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  47. await expect(throwable(false)).to.be.rejectedWith(error('false'));
  48. await expect(throwable([])).to.be.rejectedWith(error('Array'));
  49. await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
  50. await expect(throwable(null)).to.be.rejectedWith(error('null'));
  51. });
  52. it('requires the "sourceName" parameter to be a non-empty string', async function () {
  53. const dbs = new DatabaseSchema();
  54. const R = dbs.getService(ReferencesManyResolver);
  55. const error = v =>
  56. format(
  57. 'The parameter "sourceName" of ReferencesManyResolver.includeTo requires ' +
  58. 'a non-empty String, but %s was given.',
  59. v,
  60. );
  61. const throwable = v => R.includeTo([], v, 'targetName', 'relationName');
  62. await expect(throwable('')).to.be.rejectedWith(error('""'));
  63. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  64. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  65. await expect(throwable(false)).to.be.rejectedWith(error('false'));
  66. await expect(throwable([])).to.be.rejectedWith(error('Array'));
  67. await expect(throwable({})).to.be.rejectedWith(error('Object'));
  68. await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
  69. await expect(throwable(null)).to.be.rejectedWith(error('null'));
  70. });
  71. it('requires the "targetName" parameter to be a non-empty string', async function () {
  72. const dbs = new DatabaseSchema();
  73. const R = dbs.getService(ReferencesManyResolver);
  74. const error = v =>
  75. format(
  76. 'The parameter "targetName" of ReferencesManyResolver.includeTo requires ' +
  77. 'a non-empty String, but %s was given.',
  78. v,
  79. );
  80. const throwable = v => R.includeTo([], 'sourceName', v, 'relationName');
  81. await expect(throwable('')).to.be.rejectedWith(error('""'));
  82. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  83. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  84. await expect(throwable(false)).to.be.rejectedWith(error('false'));
  85. await expect(throwable([])).to.be.rejectedWith(error('Array'));
  86. await expect(throwable({})).to.be.rejectedWith(error('Object'));
  87. await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
  88. await expect(throwable(null)).to.be.rejectedWith(error('null'));
  89. });
  90. it('requires the "relationName" parameter to be a non-empty string', async function () {
  91. const dbs = new DatabaseSchema();
  92. const R = dbs.getService(ReferencesManyResolver);
  93. const error = v =>
  94. format(
  95. 'The parameter "relationName" of ReferencesManyResolver.includeTo requires ' +
  96. 'a non-empty String, but %s was given.',
  97. v,
  98. );
  99. const throwable = v => R.includeTo([], 'sourceName', 'targetName', v);
  100. await expect(throwable('')).to.be.rejectedWith(error('""'));
  101. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  102. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  103. await expect(throwable(false)).to.be.rejectedWith(error('false'));
  104. await expect(throwable([])).to.be.rejectedWith(error('Array'));
  105. await expect(throwable({})).to.be.rejectedWith(error('Object'));
  106. await expect(throwable(undefined)).to.be.rejectedWith(error('undefined'));
  107. await expect(throwable(null)).to.be.rejectedWith(error('null'));
  108. });
  109. it('requires the provided parameter "foreignKey" to be a string', async function () {
  110. const dbs = new DatabaseSchema();
  111. const R = dbs.getService(ReferencesManyResolver);
  112. const error = v =>
  113. format(
  114. 'The provided parameter "foreignKey" of ReferencesManyResolver.includeTo ' +
  115. 'should be a String, but %s was given.',
  116. v,
  117. );
  118. const throwable = v =>
  119. R.includeTo([], 'sourceName', 'targetName', 'relationName', v);
  120. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  121. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  122. await expect(throwable([])).to.be.rejectedWith(error('Array'));
  123. await expect(throwable({})).to.be.rejectedWith(error('Object'));
  124. });
  125. it('requires the provided parameter "scope" to be an object', async function () {
  126. const dbs = new DatabaseSchema();
  127. const R = dbs.getService(ReferencesManyResolver);
  128. const error = v =>
  129. format(
  130. 'The provided parameter "scope" of ReferencesManyResolver.includeTo ' +
  131. 'should be an Object, but %s was given.',
  132. v,
  133. );
  134. const throwable = v =>
  135. R.includeTo(
  136. [],
  137. 'sourceName',
  138. 'targetName',
  139. 'relationName',
  140. undefined,
  141. v,
  142. );
  143. await expect(throwable('str')).to.be.rejectedWith(error('"str"'));
  144. await expect(throwable(10)).to.be.rejectedWith(error('10'));
  145. await expect(throwable(true)).to.be.rejectedWith(error('true'));
  146. await expect(throwable([])).to.be.rejectedWith(error('Array'));
  147. });
  148. it('throws an error if the given target model is not found', async function () {
  149. const dbs = new DatabaseSchema();
  150. dbs.defineModel({name: 'source'});
  151. const R = dbs.getService(ReferencesManyResolver);
  152. const promise = R.includeTo([], 'source', 'target', 'relation');
  153. await expect(promise).to.be.rejectedWith(
  154. 'The model "target" is not defined',
  155. );
  156. });
  157. it('throws an error if the given target model does not have a datasource', async function () {
  158. const dbs = new DatabaseSchema();
  159. dbs.defineModel({name: 'target'});
  160. const R = dbs.getService(ReferencesManyResolver);
  161. const promise = R.includeTo([], 'source', 'target', 'relation');
  162. await expect(promise).to.be.rejectedWith(
  163. 'The model "target" does not have a specified datasource.',
  164. );
  165. });
  166. it('does not throw an error if a relation target is not found', async function () {
  167. const dbs = new DatabaseSchema();
  168. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  169. dbs.defineModel({name: 'source', datasource: 'datasource'});
  170. dbs.defineModel({name: 'target', datasource: 'datasource'});
  171. const sourceRel = dbs.getRepository('source');
  172. const source = await sourceRel.create({parentIds: [10, 20]});
  173. const R = dbs.getService(ReferencesManyResolver);
  174. await R.includeTo([source], 'source', 'target', 'parents');
  175. expect(source).to.be.eql({
  176. [DEF_PK]: source[DEF_PK],
  177. parentIds: [10, 20],
  178. parents: [],
  179. });
  180. });
  181. it('includes if a primary key is not defined in the target model', async function () {
  182. const dbs = new DatabaseSchema();
  183. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  184. dbs.defineModel({name: 'source', datasource: 'datasource'});
  185. dbs.defineModel({name: 'target', datasource: 'datasource'});
  186. const sourceRep = dbs.getRepository('source');
  187. const targetRep = dbs.getRepository('target');
  188. const target1 = await targetRep.create({});
  189. const target2 = await targetRep.create({});
  190. const target3 = await targetRep.create({});
  191. expect(target1).to.be.eql({[DEF_PK]: target1[DEF_PK]});
  192. expect(target2).to.be.eql({[DEF_PK]: target2[DEF_PK]});
  193. expect(target3).to.be.eql({[DEF_PK]: target3[DEF_PK]});
  194. const source = await sourceRep.create({
  195. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  196. });
  197. expect(source).to.be.eql({
  198. [DEF_PK]: source[DEF_PK],
  199. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  200. });
  201. const R = dbs.getService(ReferencesManyResolver);
  202. await R.includeTo([source], 'source', 'target', 'parents');
  203. expect(source).to.be.eql({
  204. [DEF_PK]: source[DEF_PK],
  205. parentIds: source.parentIds,
  206. parents: [target1, target2],
  207. });
  208. });
  209. it('includes if the target model has a custom primary key', async function () {
  210. const dbs = new DatabaseSchema();
  211. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  212. dbs.defineModel({name: 'source', datasource: 'datasource'});
  213. dbs.defineModel({
  214. name: 'target',
  215. datasource: 'datasource',
  216. properties: {
  217. myId: {
  218. type: DataType.NUMBER,
  219. primaryKey: true,
  220. },
  221. },
  222. });
  223. const sourceRep = dbs.getRepository('source');
  224. const targetRep = dbs.getRepository('target');
  225. const target1 = await targetRep.create({});
  226. const target2 = await targetRep.create({});
  227. const target3 = await targetRep.create({});
  228. expect(target1).to.be.eql({myId: target1.myId});
  229. expect(target2).to.be.eql({myId: target2.myId});
  230. expect(target3).to.be.eql({myId: target3.myId});
  231. const source = await sourceRep.create({
  232. parentIds: [target1.myId, target2.myId],
  233. });
  234. expect(source).to.be.eql({
  235. [DEF_PK]: source[DEF_PK],
  236. parentIds: [target1.myId, target2.myId],
  237. });
  238. const R = dbs.getService(ReferencesManyResolver);
  239. await R.includeTo([source], 'source', 'target', 'parents');
  240. expect(source).to.be.eql({
  241. [DEF_PK]: source[DEF_PK],
  242. parentIds: source.parentIds,
  243. parents: [target1, target2],
  244. });
  245. });
  246. it('includes if the source model has a custom primary key', async function () {
  247. const dbs = new DatabaseSchema();
  248. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  249. dbs.defineModel({
  250. name: 'source',
  251. datasource: 'datasource',
  252. properties: {
  253. myId: {
  254. type: DataType.NUMBER,
  255. primaryKey: true,
  256. },
  257. },
  258. });
  259. dbs.defineModel({name: 'target', datasource: 'datasource'});
  260. const sourceRep = dbs.getRepository('source');
  261. const targetRep = dbs.getRepository('target');
  262. const target1 = await targetRep.create({});
  263. const target2 = await targetRep.create({});
  264. const target3 = await targetRep.create({});
  265. expect(target1).to.be.eql({[DEF_PK]: target1[DEF_PK]});
  266. expect(target2).to.be.eql({[DEF_PK]: target2[DEF_PK]});
  267. expect(target3).to.be.eql({[DEF_PK]: target3[DEF_PK]});
  268. const source = await sourceRep.create({
  269. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  270. });
  271. expect(source).to.be.eql({
  272. myId: source.myId,
  273. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  274. });
  275. const R = dbs.getService(ReferencesManyResolver);
  276. await R.includeTo([source], 'source', 'target', 'parents');
  277. expect(source).to.be.eql({
  278. myId: source.myId,
  279. parentIds: source.parentIds,
  280. parents: [target1, target2],
  281. });
  282. });
  283. it('includes if the property "foreignKey" is specified', async function () {
  284. const dbs = new DatabaseSchema();
  285. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  286. dbs.defineModel({name: 'source', datasource: 'datasource'});
  287. dbs.defineModel({name: 'target', datasource: 'datasource'});
  288. const sourceRep = dbs.getRepository('source');
  289. const targetRep = dbs.getRepository('target');
  290. const target1 = await targetRep.create({});
  291. const target2 = await targetRep.create({});
  292. const target3 = await targetRep.create({});
  293. expect(target1).to.be.eql({[DEF_PK]: target1[DEF_PK]});
  294. expect(target2).to.be.eql({[DEF_PK]: target2[DEF_PK]});
  295. expect(target3).to.be.eql({[DEF_PK]: target3[DEF_PK]});
  296. const source = await sourceRep.create({
  297. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  298. });
  299. expect(source).to.be.eql({
  300. [DEF_PK]: source[DEF_PK],
  301. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  302. });
  303. const R = dbs.getService(ReferencesManyResolver);
  304. await R.includeTo([source], 'source', 'target', 'relations', 'parentIds');
  305. expect(source).to.be.eql({
  306. [DEF_PK]: source[DEF_PK],
  307. parentIds: source.parentIds,
  308. relations: [target1, target2],
  309. });
  310. });
  311. it('uses a where clause of the given scope to filter the relation target', async function () {
  312. const dbs = new DatabaseSchema();
  313. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  314. dbs.defineModel({name: 'source', datasource: 'datasource'});
  315. dbs.defineModel({name: 'target', datasource: 'datasource'});
  316. const sourceRep = dbs.getRepository('source');
  317. const targetRep = dbs.getRepository('target');
  318. const target1 = await targetRep.create({featured: false});
  319. const target2 = await targetRep.create({featured: true});
  320. const target3 = await targetRep.create({featured: true});
  321. expect(target1).to.be.eql({[DEF_PK]: target1[DEF_PK], featured: false});
  322. expect(target2).to.be.eql({[DEF_PK]: target2[DEF_PK], featured: true});
  323. expect(target3).to.be.eql({[DEF_PK]: target3[DEF_PK], featured: true});
  324. const source = await sourceRep.create({
  325. parentIds: [target1[DEF_PK], target2[DEF_PK], target3[DEF_PK]],
  326. });
  327. expect(source).to.be.eql({
  328. [DEF_PK]: source[DEF_PK],
  329. parentIds: [target1[DEF_PK], target2[DEF_PK], target3[DEF_PK]],
  330. });
  331. const R = dbs.getService(ReferencesManyResolver);
  332. await R.includeTo([source], 'source', 'target', 'parents', undefined, {
  333. where: {featured: false},
  334. });
  335. expect(source).to.be.eql({
  336. [DEF_PK]: source[DEF_PK],
  337. parentIds: source.parentIds,
  338. parents: [target1],
  339. });
  340. delete source.parents;
  341. await R.includeTo([source], 'source', 'target', 'parents', undefined, {
  342. where: {featured: true},
  343. });
  344. expect(source).to.be.eql({
  345. [DEF_PK]: source[DEF_PK],
  346. parentIds: source.parentIds,
  347. parents: [target2, target3],
  348. });
  349. });
  350. it('uses a slice clause of the given scope to filter the relation target', async function () {
  351. const dbs = new DatabaseSchema();
  352. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  353. dbs.defineModel({name: 'source', datasource: 'datasource'});
  354. dbs.defineModel({name: 'target', datasource: 'datasource'});
  355. const sourceRep = dbs.getRepository('source');
  356. const targetRep = dbs.getRepository('target');
  357. const target1 = await targetRep.create({});
  358. const target2 = await targetRep.create({});
  359. const target3 = await targetRep.create({});
  360. const target4 = await targetRep.create({});
  361. expect(target1).to.be.eql({[DEF_PK]: target1[DEF_PK]});
  362. expect(target2).to.be.eql({[DEF_PK]: target2[DEF_PK]});
  363. expect(target3).to.be.eql({[DEF_PK]: target3[DEF_PK]});
  364. expect(target4).to.be.eql({[DEF_PK]: target4[DEF_PK]});
  365. const source = await sourceRep.create({
  366. parentIds: [
  367. target1[DEF_PK],
  368. target2[DEF_PK],
  369. target3[DEF_PK],
  370. target4[DEF_PK],
  371. ],
  372. });
  373. expect(source).to.be.eql({
  374. [DEF_PK]: source[DEF_PK],
  375. parentIds: [
  376. target1[DEF_PK],
  377. target2[DEF_PK],
  378. target3[DEF_PK],
  379. target4[DEF_PK],
  380. ],
  381. });
  382. const R = dbs.getService(ReferencesManyResolver);
  383. await R.includeTo([source], 'source', 'target', 'parents', undefined, {
  384. skip: 1,
  385. limit: 2,
  386. });
  387. expect(source).to.be.eql({
  388. [DEF_PK]: source[DEF_PK],
  389. parentIds: source.parentIds,
  390. parents: [target2, target3],
  391. });
  392. });
  393. it('uses a fields clause of the given scope to filter the relation target', async function () {
  394. const dbs = new DatabaseSchema();
  395. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  396. dbs.defineModel({name: 'source', datasource: 'datasource'});
  397. dbs.defineModel({name: 'target', datasource: 'datasource'});
  398. const sourceRep = dbs.getRepository('source');
  399. const targetRep = dbs.getRepository('target');
  400. const target1 = await targetRep.create({
  401. foo: 'fooVal1',
  402. bar: 'barVal1',
  403. });
  404. const target2 = await targetRep.create({
  405. foo: 'fooVal2',
  406. bar: 'barVal2',
  407. });
  408. const target3 = await targetRep.create({
  409. foo: 'fooVal3',
  410. bar: 'barVal3',
  411. });
  412. expect(target1).to.be.eql({
  413. [DEF_PK]: target1[DEF_PK],
  414. foo: 'fooVal1',
  415. bar: 'barVal1',
  416. });
  417. expect(target2).to.be.eql({
  418. [DEF_PK]: target2[DEF_PK],
  419. foo: 'fooVal2',
  420. bar: 'barVal2',
  421. });
  422. expect(target3).to.be.eql({
  423. [DEF_PK]: target3[DEF_PK],
  424. foo: 'fooVal3',
  425. bar: 'barVal3',
  426. });
  427. const source = await sourceRep.create({
  428. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  429. });
  430. expect(source).to.be.eql({
  431. [DEF_PK]: source[DEF_PK],
  432. parentIds: [target1[DEF_PK], target2[DEF_PK]],
  433. });
  434. const R = dbs.getService(ReferencesManyResolver);
  435. await R.includeTo([source], 'source', 'target', 'parents', undefined, {
  436. fields: [DEF_PK, 'bar'],
  437. });
  438. expect(source).to.be.eql({
  439. [DEF_PK]: source[DEF_PK],
  440. parentIds: source.parentIds,
  441. parents: [
  442. {
  443. [DEF_PK]: target1[DEF_PK],
  444. bar: target1.bar,
  445. },
  446. {
  447. [DEF_PK]: target2[DEF_PK],
  448. bar: target2.bar,
  449. },
  450. ],
  451. });
  452. });
  453. it('uses an include clause of the given scope to resolve target relations', async function () {
  454. const dbs = new DatabaseSchema();
  455. dbs.defineDatasource({
  456. name: 'datasource',
  457. adapter: 'memory',
  458. });
  459. dbs.defineModel({
  460. name: 'modelA',
  461. datasource: 'datasource',
  462. properties: {
  463. id: {
  464. type: DataType.NUMBER,
  465. primaryKey: true,
  466. },
  467. source: {
  468. type: DataType.STRING,
  469. default: 'modelA',
  470. },
  471. },
  472. });
  473. dbs.defineModel({
  474. name: 'modelB',
  475. datasource: 'datasource',
  476. properties: {
  477. id: {
  478. type: DataType.NUMBER,
  479. primaryKey: true,
  480. },
  481. source: {
  482. type: DataType.STRING,
  483. default: 'modelB',
  484. },
  485. },
  486. relations: {
  487. parent: {
  488. type: RelationType.BELONGS_TO,
  489. model: 'modelA',
  490. },
  491. },
  492. });
  493. dbs.defineModel({
  494. name: 'modelC',
  495. datasource: 'datasource',
  496. properties: {
  497. id: {
  498. type: DataType.NUMBER,
  499. primaryKey: true,
  500. },
  501. source: {
  502. type: DataType.STRING,
  503. default: 'modelC',
  504. },
  505. },
  506. relations: {
  507. parents: {
  508. type: RelationType.REFERENCES_MANY,
  509. model: 'modelB',
  510. },
  511. },
  512. });
  513. const aRep = dbs.getRepository('modelA');
  514. const bRep = dbs.getRepository('modelB');
  515. const cRep = dbs.getRepository('modelC');
  516. const a1 = await aRep.create({});
  517. const a2 = await aRep.create({});
  518. const b1 = await bRep.create({parentId: a1.id});
  519. const b2 = await bRep.create({parentId: a2.id});
  520. const c = await cRep.create({parentIds: [b1.id, b2.id]});
  521. expect(a1).to.be.eql({
  522. id: a1.id,
  523. source: 'modelA',
  524. });
  525. expect(a2).to.be.eql({
  526. id: a2.id,
  527. source: 'modelA',
  528. });
  529. expect(b1).to.be.eql({
  530. id: b1.id,
  531. source: 'modelB',
  532. parentId: a1.id,
  533. });
  534. expect(b2).to.be.eql({
  535. id: b2.id,
  536. source: 'modelB',
  537. parentId: a2.id,
  538. });
  539. expect(c).to.be.eql({
  540. id: c.id,
  541. source: 'modelC',
  542. parentIds: [b1.id, b2.id],
  543. });
  544. const R = dbs.getService(ReferencesManyResolver);
  545. await R.includeTo([c], 'modelC', 'modelB', 'parents', undefined, {
  546. include: 'parent',
  547. });
  548. expect(c).to.be.eql({
  549. id: c.id,
  550. source: 'modelC',
  551. parentIds: [b1.id, b2.id],
  552. parents: [
  553. {
  554. id: b1.id,
  555. source: 'modelB',
  556. parentId: a1.id,
  557. parent: {
  558. id: a1.id,
  559. source: 'modelA',
  560. },
  561. },
  562. {
  563. id: b2.id,
  564. source: 'modelB',
  565. parentId: a2.id,
  566. parent: {
  567. id: a2.id,
  568. source: 'modelA',
  569. },
  570. },
  571. ],
  572. });
  573. });
  574. it('does not break the "and" operator of the given "where" clause', async function () {
  575. const dbs = new DatabaseSchema();
  576. dbs.defineDatasource({name: 'datasource', adapter: 'memory'});
  577. dbs.defineModel({name: 'source', datasource: 'datasource'});
  578. dbs.defineModel({name: 'target', datasource: 'datasource'});
  579. const sourceRep = dbs.getRepository('source');
  580. const targetRep = dbs.getRepository('target');
  581. const target1 = await targetRep.create({featured: false});
  582. const target2 = await targetRep.create({featured: true});
  583. const target3 = await targetRep.create({featured: true});
  584. expect(target1).to.be.eql({[DEF_PK]: target1[DEF_PK], featured: false});
  585. expect(target2).to.be.eql({[DEF_PK]: target2[DEF_PK], featured: true});
  586. expect(target3).to.be.eql({[DEF_PK]: target3[DEF_PK], featured: true});
  587. const source = await sourceRep.create({
  588. parentIds: [target1[DEF_PK], target2[DEF_PK], target3[DEF_PK]],
  589. });
  590. expect(source).to.be.eql({
  591. [DEF_PK]: source[DEF_PK],
  592. parentIds: [target1[DEF_PK], target2[DEF_PK], target3[DEF_PK]],
  593. });
  594. const R = dbs.getService(ReferencesManyResolver);
  595. await R.includeTo([source], 'source', 'target', 'parents', undefined, {
  596. where: {and: [{featured: false}]},
  597. });
  598. expect(source).to.be.eql({
  599. [DEF_PK]: source[DEF_PK],
  600. parentIds: source.parentIds,
  601. parents: [target1],
  602. });
  603. delete source.parents;
  604. await R.includeTo([source], 'source', 'target', 'parents', undefined, {
  605. where: {and: [{featured: true}]},
  606. });
  607. expect(source).to.be.eql({
  608. [DEF_PK]: source[DEF_PK],
  609. parentIds: source.parentIds,
  610. parents: [target2, target3],
  611. });
  612. });
  613. });
  614. });