references-many-resolver.spec.js 24 KB

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