HATEOAS-first backend framework.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

107 Zeilen
2.2 KiB

  1. import {describe, afterAll, afterEach, beforeAll, beforeEach, it} from 'vitest';
  2. import {mkdtemp, rm} from 'fs/promises';
  3. import {join} from 'path';
  4. import {tmpdir} from 'os';
  5. import {application, resource, Resource, validation as v} from '../../src/common';
  6. import {BackendBuilder, dataSources} from '../../src/backend';
  7. import {autoIncrement} from '../fixtures';
  8. import {RequestContext} from '../../src/backend/common';
  9. const PORT = 3001;
  10. const HOST = '127.0.0.1';
  11. const BASE_PATH = '/api';
  12. const ACCEPT = 'application/json';
  13. const ACCEPT_LANGUAGE = 'en';
  14. const CONTENT_TYPE_CHARSET = 'utf-8';
  15. const CONTENT_TYPE = ACCEPT;
  16. describe('decorators', () => {
  17. let baseDir: string;
  18. beforeAll(async () => {
  19. try {
  20. baseDir = await mkdtemp(join(tmpdir(), 'yasumi-'));
  21. } catch {
  22. // noop
  23. }
  24. });
  25. afterAll(async () => {
  26. try {
  27. await rm(baseDir, {
  28. recursive: true,
  29. });
  30. } catch {
  31. // noop
  32. }
  33. });
  34. let Piano: Resource;
  35. beforeEach(() => {
  36. Piano = resource(v.object(
  37. {
  38. brand: v.string()
  39. },
  40. v.never()
  41. ))
  42. .name('Piano' as const)
  43. .route('pianos' as const)
  44. .id('id' as const, {
  45. generationStrategy: autoIncrement,
  46. serialize: (id) => id?.toString() ?? '0',
  47. deserialize: (id) => Number.isFinite(Number(id)) ? Number(id) : 0,
  48. schema: v.number(),
  49. });
  50. });
  51. let server: ReturnType<BackendBuilder['createHttpServer']>;
  52. beforeEach(() => {
  53. const app = application({
  54. name: 'piano-service',
  55. })
  56. .resource(Piano);
  57. const backend = app
  58. .createBackend({
  59. dataSource: new dataSources.jsonlFile.DataSource(baseDir),
  60. })
  61. .throwsErrorOnDeletingNotFound();
  62. server = backend.createHttpServer({
  63. basePath: BASE_PATH
  64. });
  65. return new Promise((resolve, reject) => {
  66. server.on('error', (err) => {
  67. reject(err);
  68. });
  69. server.on('listening', () => {
  70. resolve();
  71. });
  72. server.listen({
  73. port: PORT
  74. });
  75. });
  76. });
  77. afterEach(() => new Promise((resolve, reject) => {
  78. server.close((err) => {
  79. if (err) {
  80. reject(err);
  81. }
  82. resolve();
  83. });
  84. }));
  85. it('decorates requests', () => {
  86. server.requestDecorator((req) => {
  87. const reqMut = req as unknown as Record<string, unknown>;
  88. reqMut['foo'] = 'bar';
  89. return reqMut as unknown as RequestContext;
  90. });
  91. // TODO how to make assertions here
  92. });
  93. });