HATEOAS-first backend framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

default.test.ts 3.5 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import {
  2. describe,
  3. beforeAll,
  4. afterAll,
  5. it,
  6. expect,
  7. vi, Mock,
  8. } from 'vitest';
  9. import {
  10. app,
  11. Endpoint,
  12. Operation,
  13. } from '../../src/common';
  14. import {DataSource, DataSourceQuery, EmplaceDetails, Server} from '../../src/backend';
  15. import {Client} from '../../src/client';
  16. import {server} from '../../src/extenders/http/backend';
  17. import {client} from '../../src/extenders/http/client';
  18. import {composeRecipes} from '../../src/common/recipe';
  19. import {addResourceRecipe, ResourceItemFetchedResponse} from '../../src/recipes/resource';
  20. describe('default', () => {
  21. let theClient: Client;
  22. let theServer: Server;
  23. let theRawEndpoint: Endpoint;
  24. let theOperation: Operation;
  25. let dataSource: Record<keyof DataSource, Mock>;
  26. beforeAll(() => {
  27. dataSource = {
  28. create: vi.fn(async (data) => data),
  29. getById: vi.fn(async () => ({})),
  30. delete: vi.fn(),
  31. emplace: vi.fn(async () => [{}, { isCreated: false }]),
  32. getMultiple: vi.fn(async () => []),
  33. getSingle: vi.fn(async () => ({})),
  34. getTotalCount: vi.fn(async () => 1),
  35. newId: vi.fn(async () => 1),
  36. patch: vi.fn(async (id, data) => ({ ...data, id })),
  37. initialize: vi.fn(async () => {}),
  38. };
  39. });
  40. afterAll(() => {
  41. dataSource.getById.mockReset();
  42. });
  43. beforeAll(async () => {
  44. const theRawApp = app({
  45. name: 'default' as const,
  46. });
  47. const {
  48. app: theApp,
  49. operations,
  50. backend: theBackend,
  51. } = composeRecipes([
  52. addResourceRecipe({ endpointName: 'users', dataSource, }),
  53. addResourceRecipe({ endpointName: 'posts', dataSource, })
  54. ])({
  55. app: theRawApp,
  56. });
  57. theRawEndpoint = Array.from(theApp.endpoints).find((e) => e.name === 'users');
  58. theOperation = operations.fetch;
  59. theServer = server({
  60. backend: theBackend,
  61. });
  62. const connectionParams = {
  63. port: 3001,
  64. };
  65. await theServer.serve(connectionParams);
  66. theClient = client({
  67. app: theApp,
  68. });
  69. await theClient.connect(connectionParams);
  70. });
  71. afterAll(async () => {
  72. await theClient.disconnect();
  73. await theServer.close();
  74. });
  75. it('works', async () => {
  76. // TODO create wrapper for fetch's Response here
  77. //
  78. // should we create a helper object to process client-side received response from server's sent response?
  79. //
  80. // the motivation is to remove the manual deserialization from the client (provide serialization on the response
  81. // object so as the client is not limited to .text(), .json(), .arrayBuffer() etc)
  82. const responseRaw = await theClient
  83. .at(theRawEndpoint)
  84. .makeRequest(theOperation, new URLSearchParams({
  85. foo: 'bar',
  86. }));
  87. const response = ResourceItemFetchedResponse.fromFetchResponse(responseRaw);
  88. expect(response).toHaveProperty('statusCode', 200);
  89. expect(response).toHaveProperty('statusMessage', 'Resource Collection Fetched');
  90. });
  91. it('works for items', async () => {
  92. // TODO create wrapper for fetch's Response here
  93. //
  94. // should we create a helper object to process client-side received response from server's sent response?
  95. //
  96. // the motivation is to remove the manual deserialization from the client (provide serialization on the response
  97. // object so as the client is not limited to .text(), .json(), .arrayBuffer() etc)
  98. const responseRaw = await theClient
  99. .at(theRawEndpoint, { resourceId: 3 })
  100. .makeRequest(theOperation, new URLSearchParams({
  101. foo: 'bar',
  102. }));
  103. const response = ResourceItemFetchedResponse.fromFetchResponse(responseRaw);
  104. expect(response).toHaveProperty('statusCode', 200);
  105. expect(response).toHaveProperty('statusMessage', 'Resource Item Fetched');
  106. });
  107. });