list-query-builder.e2e-spec.ts 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. import { LogicalOperator } from '@vendure/common/lib/generated-types';
  2. import { mergeConfig } from '@vendure/core';
  3. import { createTestEnvironment } from '@vendure/testing';
  4. import gql from 'graphql-tag';
  5. import path from 'path';
  6. import { initialData } from '../../../e2e-common/e2e-initial-data';
  7. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  8. import { ListQueryPlugin } from './fixtures/test-plugins/list-query-plugin';
  9. import { LanguageCode, SortOrder } from './graphql/generated-e2e-admin-types';
  10. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  11. import { fixPostgresTimezone } from './utils/fix-pg-timezone';
  12. fixPostgresTimezone();
  13. describe('ListQueryBuilder', () => {
  14. const { server, adminClient, shopClient } = createTestEnvironment(
  15. mergeConfig(testConfig(), {
  16. apiOptions: {
  17. shopListQueryLimit: 10,
  18. adminListQueryLimit: 30,
  19. },
  20. plugins: [ListQueryPlugin],
  21. }),
  22. );
  23. beforeAll(async () => {
  24. await server.init({
  25. initialData,
  26. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  27. customerCount: 1,
  28. });
  29. await adminClient.asSuperAdmin();
  30. }, TEST_SETUP_TIMEOUT_MS);
  31. afterAll(async () => {
  32. await server.destroy();
  33. });
  34. function getItemLabels(items: any[]): string[] {
  35. return items.map((x: any) => x.label).sort();
  36. }
  37. describe('pagination', () => {
  38. it('all en', async () => {
  39. const { testEntities } = await adminClient.query(
  40. GET_LIST,
  41. {
  42. options: {},
  43. },
  44. { languageCode: LanguageCode.en },
  45. );
  46. expect(testEntities.totalItems).toBe(6);
  47. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'C', 'D', 'E', 'F']);
  48. expect(testEntities.items.map((i: any) => i.name)).toEqual([
  49. 'apple',
  50. 'bike',
  51. 'cake',
  52. 'dog',
  53. 'egg',
  54. 'baum', // if default en lang does not exist, use next available lang
  55. ]);
  56. });
  57. it('all de', async () => {
  58. const { testEntities } = await adminClient.query(
  59. GET_LIST,
  60. {
  61. options: {},
  62. },
  63. { languageCode: LanguageCode.de },
  64. );
  65. expect(testEntities.totalItems).toBe(6);
  66. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'C', 'D', 'E', 'F']);
  67. expect(testEntities.items.map((i: any) => i.name)).toEqual([
  68. 'apfel',
  69. 'fahrrad',
  70. 'kuchen',
  71. 'hund',
  72. 'egg', // falls back to en translation when de doesn't exist
  73. 'baum',
  74. ]);
  75. });
  76. it('take', async () => {
  77. const { testEntities } = await adminClient.query(GET_LIST, {
  78. options: {
  79. take: 2,
  80. },
  81. });
  82. expect(testEntities.totalItems).toBe(6);
  83. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B']);
  84. });
  85. it('skip', async () => {
  86. const { testEntities } = await adminClient.query(GET_LIST, {
  87. options: {
  88. skip: 2,
  89. },
  90. });
  91. expect(testEntities.totalItems).toBe(6);
  92. expect(getItemLabels(testEntities.items)).toEqual(['C', 'D', 'E', 'F']);
  93. });
  94. it('skip negative is ignored', async () => {
  95. const { testEntities } = await adminClient.query(GET_LIST, {
  96. options: {
  97. skip: -1,
  98. },
  99. });
  100. expect(testEntities.totalItems).toBe(6);
  101. expect(testEntities.items.length).toBe(6);
  102. });
  103. it('take zero is ignored', async () => {
  104. const { testEntities } = await adminClient.query(GET_LIST, {
  105. options: {
  106. take: 0,
  107. },
  108. });
  109. expect(testEntities.totalItems).toBe(6);
  110. expect(testEntities.items.length).toBe(6);
  111. });
  112. it('take negative is ignored', async () => {
  113. const { testEntities } = await adminClient.query(GET_LIST, {
  114. options: {
  115. take: -1,
  116. },
  117. });
  118. expect(testEntities.totalItems).toBe(6);
  119. expect(testEntities.items.length).toBe(6);
  120. });
  121. it(
  122. 'take beyond adminListQueryLimit',
  123. assertThrowsWithMessage(async () => {
  124. await adminClient.query(GET_LIST, {
  125. options: {
  126. take: 50,
  127. },
  128. });
  129. }, 'Cannot take more than 30 results from a list query'),
  130. );
  131. it(
  132. 'take beyond shopListQueryLimit',
  133. assertThrowsWithMessage(async () => {
  134. await shopClient.query(GET_LIST, {
  135. options: {
  136. take: 50,
  137. },
  138. });
  139. }, 'Cannot take more than 10 results from a list query'),
  140. );
  141. });
  142. describe('string filtering', () => {
  143. it('eq', async () => {
  144. const { testEntities } = await adminClient.query(GET_LIST, {
  145. options: {
  146. filter: {
  147. label: {
  148. eq: 'B',
  149. },
  150. },
  151. },
  152. });
  153. expect(getItemLabels(testEntities.items)).toEqual(['B']);
  154. });
  155. it('notEq', async () => {
  156. const { testEntities } = await adminClient.query(GET_LIST, {
  157. options: {
  158. filter: {
  159. label: {
  160. notEq: 'B',
  161. },
  162. },
  163. },
  164. });
  165. expect(getItemLabels(testEntities.items)).toEqual(['A', 'C', 'D', 'E', 'F']);
  166. });
  167. it('contains', async () => {
  168. const { testEntities } = await adminClient.query(GET_LIST, {
  169. options: {
  170. filter: {
  171. description: {
  172. contains: 'adip',
  173. },
  174. },
  175. },
  176. });
  177. expect(getItemLabels(testEntities.items)).toEqual(['C']);
  178. });
  179. it('notContains', async () => {
  180. const { testEntities } = await adminClient.query(GET_LIST, {
  181. options: {
  182. filter: {
  183. description: {
  184. notContains: 'te',
  185. },
  186. },
  187. },
  188. });
  189. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'E', 'F']);
  190. });
  191. it('in', async () => {
  192. const { testEntities } = await adminClient.query(GET_LIST, {
  193. options: {
  194. filter: {
  195. label: {
  196. in: ['A', 'C'],
  197. },
  198. },
  199. },
  200. });
  201. expect(getItemLabels(testEntities.items)).toEqual(['A', 'C']);
  202. });
  203. it('notIn', async () => {
  204. const { testEntities } = await adminClient.query(GET_LIST, {
  205. options: {
  206. filter: {
  207. label: {
  208. notIn: ['A', 'C'],
  209. },
  210. },
  211. },
  212. });
  213. expect(getItemLabels(testEntities.items)).toEqual(['B', 'D', 'E', 'F']);
  214. });
  215. describe('regex', () => {
  216. it('simple substring', async () => {
  217. const { testEntities } = await adminClient.query(GET_LIST, {
  218. options: {
  219. filter: {
  220. description: {
  221. regex: 'or',
  222. },
  223. },
  224. },
  225. });
  226. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'D']);
  227. });
  228. it('start of string', async () => {
  229. const { testEntities } = await adminClient.query(GET_LIST, {
  230. options: {
  231. filter: {
  232. description: {
  233. regex: '^in',
  234. },
  235. },
  236. },
  237. });
  238. expect(getItemLabels(testEntities.items)).toEqual(['E']);
  239. });
  240. it('end of string', async () => {
  241. const { testEntities } = await adminClient.query(GET_LIST, {
  242. options: {
  243. filter: {
  244. description: {
  245. regex: 'or$',
  246. },
  247. },
  248. },
  249. });
  250. expect(getItemLabels(testEntities.items)).toEqual(['D']);
  251. });
  252. it('alternation', async () => {
  253. const { testEntities } = await adminClient.query(GET_LIST, {
  254. options: {
  255. filter: {
  256. description: {
  257. regex: 'dolor|tempor',
  258. },
  259. },
  260. },
  261. });
  262. expect(getItemLabels(testEntities.items)).toEqual(['B', 'D']);
  263. });
  264. it('complex', async () => {
  265. const { testEntities } = await adminClient.query(GET_LIST, {
  266. options: {
  267. filter: {
  268. description: {
  269. regex: '(dolor|tempor)|inc[i]?d[^a]d.*nt',
  270. },
  271. },
  272. },
  273. });
  274. expect(getItemLabels(testEntities.items)).toEqual(['B', 'D', 'E']);
  275. });
  276. });
  277. });
  278. describe('ID filtering', () => {
  279. it('eq', async () => {
  280. const { testEntities } = await adminClient.query(GET_LIST, {
  281. options: {
  282. filter: {
  283. ownerId: {
  284. eq: '13',
  285. },
  286. },
  287. },
  288. });
  289. expect(getItemLabels(testEntities.items)).toEqual(['D']);
  290. });
  291. it('notEq', async () => {
  292. const { testEntities } = await adminClient.query(GET_LIST, {
  293. options: {
  294. filter: {
  295. ownerId: {
  296. notEq: '13',
  297. },
  298. },
  299. },
  300. });
  301. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'C', 'E', 'F']);
  302. });
  303. it('in', async () => {
  304. const { testEntities } = await adminClient.query(GET_LIST, {
  305. options: {
  306. filter: {
  307. ownerId: {
  308. in: ['10', '15'],
  309. },
  310. },
  311. },
  312. });
  313. expect(getItemLabels(testEntities.items)).toEqual(['A', 'F']);
  314. });
  315. it('notIn', async () => {
  316. const { testEntities } = await adminClient.query(GET_LIST, {
  317. options: {
  318. filter: {
  319. ownerId: {
  320. notIn: ['10', '15'],
  321. },
  322. },
  323. },
  324. });
  325. expect(getItemLabels(testEntities.items)).toEqual(['B', 'C', 'D', 'E']);
  326. });
  327. describe('regex', () => {
  328. it('simple substring', async () => {
  329. const { testEntities } = await adminClient.query(GET_LIST, {
  330. options: {
  331. filter: {
  332. description: {
  333. regex: 'or',
  334. },
  335. },
  336. },
  337. });
  338. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'D']);
  339. });
  340. it('start of string', async () => {
  341. const { testEntities } = await adminClient.query(GET_LIST, {
  342. options: {
  343. filter: {
  344. description: {
  345. regex: '^in',
  346. },
  347. },
  348. },
  349. });
  350. expect(getItemLabels(testEntities.items)).toEqual(['E']);
  351. });
  352. it('end of string', async () => {
  353. const { testEntities } = await adminClient.query(GET_LIST, {
  354. options: {
  355. filter: {
  356. description: {
  357. regex: 'or$',
  358. },
  359. },
  360. },
  361. });
  362. expect(getItemLabels(testEntities.items)).toEqual(['D']);
  363. });
  364. it('alternation', async () => {
  365. const { testEntities } = await adminClient.query(GET_LIST, {
  366. options: {
  367. filter: {
  368. description: {
  369. regex: 'dolor|tempor',
  370. },
  371. },
  372. },
  373. });
  374. expect(getItemLabels(testEntities.items)).toEqual(['B', 'D']);
  375. });
  376. it('complex', async () => {
  377. const { testEntities } = await adminClient.query(GET_LIST, {
  378. options: {
  379. filter: {
  380. description: {
  381. regex: '(dolor|tempor)|inc[i]?d[^a]d.*nt',
  382. },
  383. },
  384. },
  385. });
  386. expect(getItemLabels(testEntities.items)).toEqual(['B', 'D', 'E']);
  387. });
  388. });
  389. });
  390. describe('boolean filtering', () => {
  391. it('eq', async () => {
  392. const { testEntities } = await adminClient.query(GET_LIST, {
  393. options: {
  394. filter: {
  395. active: {
  396. eq: false,
  397. },
  398. },
  399. },
  400. });
  401. expect(getItemLabels(testEntities.items)).toEqual(['C', 'E', 'F']);
  402. });
  403. });
  404. describe('number filtering', () => {
  405. it('eq', async () => {
  406. const { testEntities } = await adminClient.query(GET_LIST, {
  407. options: {
  408. filter: {
  409. order: {
  410. eq: 1,
  411. },
  412. },
  413. },
  414. });
  415. expect(getItemLabels(testEntities.items)).toEqual(['B']);
  416. });
  417. it('lt', async () => {
  418. const { testEntities } = await adminClient.query(GET_LIST, {
  419. options: {
  420. filter: {
  421. order: {
  422. lt: 1,
  423. },
  424. },
  425. },
  426. });
  427. expect(getItemLabels(testEntities.items)).toEqual(['A']);
  428. });
  429. it('lte', async () => {
  430. const { testEntities } = await adminClient.query(GET_LIST, {
  431. options: {
  432. filter: {
  433. order: {
  434. lte: 1,
  435. },
  436. },
  437. },
  438. });
  439. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B']);
  440. });
  441. it('gt', async () => {
  442. const { testEntities } = await adminClient.query(GET_LIST, {
  443. options: {
  444. filter: {
  445. order: {
  446. gt: 1,
  447. },
  448. },
  449. },
  450. });
  451. expect(getItemLabels(testEntities.items)).toEqual(['C', 'D', 'E', 'F']);
  452. });
  453. it('gte', async () => {
  454. const { testEntities } = await adminClient.query(GET_LIST, {
  455. options: {
  456. filter: {
  457. order: {
  458. gte: 1,
  459. },
  460. },
  461. },
  462. });
  463. expect(getItemLabels(testEntities.items)).toEqual(['B', 'C', 'D', 'E', 'F']);
  464. });
  465. it('between', async () => {
  466. const { testEntities } = await adminClient.query(GET_LIST, {
  467. options: {
  468. filter: {
  469. order: {
  470. between: {
  471. start: 2,
  472. end: 4,
  473. },
  474. },
  475. },
  476. },
  477. });
  478. expect(getItemLabels(testEntities.items)).toEqual(['C', 'D', 'E']);
  479. });
  480. });
  481. describe('date filtering', () => {
  482. it('before', async () => {
  483. const { testEntities } = await adminClient.query(GET_LIST, {
  484. options: {
  485. filter: {
  486. date: {
  487. before: '2020-01-20T10:00:00.000Z',
  488. },
  489. },
  490. },
  491. });
  492. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B']);
  493. });
  494. it('before on same date', async () => {
  495. const { testEntities } = await adminClient.query(GET_LIST, {
  496. options: {
  497. filter: {
  498. date: {
  499. before: '2020-01-15T17:00:00.000Z',
  500. },
  501. },
  502. },
  503. });
  504. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B']);
  505. });
  506. it('after', async () => {
  507. const { testEntities } = await adminClient.query(GET_LIST, {
  508. options: {
  509. filter: {
  510. date: {
  511. after: '2020-01-20T10:00:00.000Z',
  512. },
  513. },
  514. },
  515. });
  516. expect(getItemLabels(testEntities.items)).toEqual(['C', 'D', 'E', 'F']);
  517. });
  518. it('after on same date', async () => {
  519. const { testEntities } = await adminClient.query(GET_LIST, {
  520. options: {
  521. filter: {
  522. date: {
  523. after: '2020-01-25T09:00:00.000Z',
  524. },
  525. },
  526. },
  527. });
  528. expect(getItemLabels(testEntities.items)).toEqual(['C', 'D', 'E', 'F']);
  529. });
  530. it('between', async () => {
  531. const { testEntities } = await adminClient.query(GET_LIST, {
  532. options: {
  533. filter: {
  534. date: {
  535. between: {
  536. start: '2020-01-10T10:00:00.000Z',
  537. end: '2020-01-20T10:00:00.000Z',
  538. },
  539. },
  540. },
  541. },
  542. });
  543. expect(getItemLabels(testEntities.items)).toEqual(['B']);
  544. });
  545. });
  546. describe('multiple filters with filterOperator', () => {
  547. it('default AND', async () => {
  548. const { testEntities } = await adminClient.query(GET_LIST, {
  549. options: {
  550. filter: {
  551. description: {
  552. contains: 'Lorem',
  553. },
  554. active: {
  555. eq: false,
  556. },
  557. },
  558. },
  559. });
  560. expect(getItemLabels(testEntities.items)).toEqual([]);
  561. });
  562. it('explicit AND', async () => {
  563. const { testEntities } = await adminClient.query(GET_LIST, {
  564. options: {
  565. filter: {
  566. description: {
  567. contains: 'Lorem',
  568. },
  569. active: {
  570. eq: false,
  571. },
  572. },
  573. filterOperator: LogicalOperator.AND,
  574. },
  575. });
  576. expect(getItemLabels(testEntities.items)).toEqual([]);
  577. });
  578. it('explicit OR', async () => {
  579. const { testEntities } = await adminClient.query(GET_LIST, {
  580. options: {
  581. filter: {
  582. description: {
  583. contains: 'Lorem',
  584. },
  585. active: {
  586. eq: false,
  587. },
  588. },
  589. filterOperator: LogicalOperator.OR,
  590. },
  591. });
  592. expect(getItemLabels(testEntities.items)).toEqual(['A', 'C', 'E', 'F']);
  593. });
  594. it('explicit OR with 3 filters', async () => {
  595. const { testEntities } = await adminClient.query(GET_LIST, {
  596. options: {
  597. filter: {
  598. description: {
  599. contains: 'eiusmod',
  600. },
  601. active: {
  602. eq: false,
  603. },
  604. order: {
  605. lt: 3,
  606. },
  607. },
  608. filterOperator: LogicalOperator.OR,
  609. },
  610. });
  611. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'C', 'D', 'E', 'F']);
  612. });
  613. it('explicit OR with empty filters object', async () => {
  614. const { testEntities } = await adminClient.query(GET_LIST, {
  615. options: {
  616. filter: {},
  617. filterOperator: LogicalOperator.OR,
  618. },
  619. });
  620. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'C', 'D', 'E', 'F']);
  621. });
  622. });
  623. describe('sorting', () => {
  624. it('sort by string', async () => {
  625. const { testEntities } = await adminClient.query(GET_LIST, {
  626. options: {
  627. sort: {
  628. label: SortOrder.DESC,
  629. },
  630. },
  631. });
  632. expect(testEntities.items.map((x: any) => x.label)).toEqual(['F', 'E', 'D', 'C', 'B', 'A']);
  633. });
  634. it('sort by number', async () => {
  635. const { testEntities } = await adminClient.query(GET_LIST, {
  636. options: {
  637. sort: {
  638. order: SortOrder.DESC,
  639. },
  640. },
  641. });
  642. expect(testEntities.items.map((x: any) => x.label)).toEqual(['F', 'E', 'D', 'C', 'B', 'A']);
  643. });
  644. it('sort by date', async () => {
  645. const { testEntities } = await adminClient.query(GET_LIST, {
  646. options: {
  647. sort: {
  648. date: SortOrder.DESC,
  649. },
  650. },
  651. });
  652. expect(testEntities.items.map((x: any) => x.label)).toEqual(['F', 'E', 'D', 'C', 'B', 'A']);
  653. });
  654. it('sort by ID', async () => {
  655. const { testEntities } = await adminClient.query(GET_LIST, {
  656. options: {
  657. sort: {
  658. id: SortOrder.DESC,
  659. },
  660. },
  661. });
  662. expect(testEntities.items.map((x: any) => x.label)).toEqual(['F', 'E', 'D', 'C', 'B', 'A']);
  663. });
  664. it('sort by translated field en', async () => {
  665. const { testEntities } = await adminClient.query(GET_LIST, {
  666. options: {
  667. sort: {
  668. name: SortOrder.ASC,
  669. },
  670. },
  671. });
  672. expect(testEntities.items.map((x: any) => x.name)).toEqual([
  673. 'apple',
  674. 'baum', // falling back to de here
  675. 'bike',
  676. 'cake',
  677. 'dog',
  678. 'egg',
  679. ]);
  680. });
  681. it('sort by translated field de', async () => {
  682. const { testEntities } = await adminClient.query(
  683. GET_LIST,
  684. {
  685. options: {
  686. sort: {
  687. name: SortOrder.ASC,
  688. },
  689. },
  690. },
  691. { languageCode: LanguageCode.de },
  692. );
  693. expect(testEntities.items.map((x: any) => x.name)).toEqual([
  694. 'apfel',
  695. 'baum',
  696. 'egg',
  697. 'fahrrad',
  698. 'hund',
  699. 'kuchen',
  700. ]);
  701. });
  702. it('sort by translated field en with take', async () => {
  703. const { testEntities } = await adminClient.query(GET_LIST, {
  704. options: {
  705. sort: {
  706. name: SortOrder.ASC,
  707. },
  708. take: 4,
  709. },
  710. });
  711. expect(testEntities.items.map((x: any) => x.name)).toEqual(['apple', 'baum', 'bike', 'cake']);
  712. });
  713. it('sort by translated field de with take', async () => {
  714. const { testEntities } = await adminClient.query(
  715. GET_LIST,
  716. {
  717. options: {
  718. sort: {
  719. name: SortOrder.ASC,
  720. },
  721. take: 4,
  722. },
  723. },
  724. { languageCode: LanguageCode.de },
  725. );
  726. expect(testEntities.items.map((x: any) => x.name)).toEqual(['apfel', 'baum', 'egg', 'fahrrad']);
  727. });
  728. });
  729. describe('calculated fields', () => {
  730. it('filter by simple calculated property', async () => {
  731. const { testEntities } = await adminClient.query(GET_LIST, {
  732. options: {
  733. filter: {
  734. descriptionLength: {
  735. lt: 12,
  736. },
  737. },
  738. },
  739. });
  740. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B']);
  741. });
  742. it('filter by calculated property with join', async () => {
  743. const { testEntities } = await adminClient.query(GET_LIST, {
  744. options: {
  745. filter: {
  746. price: {
  747. lt: 14,
  748. },
  749. },
  750. },
  751. });
  752. expect(getItemLabels(testEntities.items)).toEqual(['A', 'B', 'E']);
  753. });
  754. it('sort by simple calculated property', async () => {
  755. const { testEntities } = await adminClient.query(GET_LIST, {
  756. options: {
  757. sort: {
  758. descriptionLength: SortOrder.ASC,
  759. },
  760. },
  761. });
  762. expect(testEntities.items.map((x: any) => x.label)).toEqual(['B', 'A', 'E', 'D', 'C', 'F']);
  763. });
  764. it('sort by calculated property with join', async () => {
  765. const { testEntities } = await adminClient.query(GET_LIST, {
  766. options: {
  767. sort: {
  768. price: SortOrder.ASC,
  769. },
  770. },
  771. });
  772. expect(testEntities.items.map((x: any) => x.label)).toEqual(['B', 'A', 'E', 'D', 'C', 'F']);
  773. });
  774. });
  775. describe('multiple clauses', () => {
  776. it('sort by translated field en & filter', async () => {
  777. const { testEntities } = await adminClient.query(GET_LIST, {
  778. options: {
  779. sort: {
  780. name: SortOrder.ASC,
  781. },
  782. filter: {
  783. order: {
  784. gte: 1,
  785. },
  786. },
  787. },
  788. });
  789. expect(testEntities.items.map((x: any) => x.name)).toEqual([
  790. 'baum',
  791. 'bike',
  792. 'cake',
  793. 'dog',
  794. 'egg',
  795. ]);
  796. });
  797. it('sort by translated field de & filter', async () => {
  798. const { testEntities } = await adminClient.query(
  799. GET_LIST,
  800. {
  801. options: {
  802. sort: {
  803. name: SortOrder.ASC,
  804. },
  805. filter: {
  806. order: {
  807. gte: 1,
  808. },
  809. },
  810. },
  811. },
  812. { languageCode: LanguageCode.de },
  813. );
  814. expect(testEntities.items.map((x: any) => x.name)).toEqual([
  815. 'baum',
  816. 'egg',
  817. 'fahrrad',
  818. 'hund',
  819. 'kuchen',
  820. ]);
  821. });
  822. it('sort by translated field de & filter & pagination', async () => {
  823. const { testEntities } = await adminClient.query(
  824. GET_LIST,
  825. {
  826. options: {
  827. sort: {
  828. name: SortOrder.ASC,
  829. },
  830. filter: {
  831. order: {
  832. gte: 1,
  833. },
  834. },
  835. take: 2,
  836. skip: 1,
  837. },
  838. },
  839. { languageCode: LanguageCode.de },
  840. );
  841. expect(testEntities.items.map((x: any) => x.name)).toEqual(['egg', 'fahrrad']);
  842. });
  843. });
  844. });
  845. const GET_LIST = gql`
  846. query GetTestEntities($options: TestEntityListOptions) {
  847. testEntities(options: $options) {
  848. totalItems
  849. items {
  850. id
  851. label
  852. name
  853. date
  854. }
  855. }
  856. }
  857. `;