request-context.spec.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import {expect} from 'chai';
  2. import {format} from '@e22m4u/js-format';
  3. import {RequestContext} from './request-context.js';
  4. import {ServiceContainer} from '@e22m4u/js-service';
  5. import {
  6. createRouteMock,
  7. createRequestMock,
  8. createResponseMock,
  9. } from './utils/index.js';
  10. describe('RequestContext', function () {
  11. describe('constructor', function () {
  12. it('requires the parameter "container" to be a ServiceContainer instance', function () {
  13. const req = createRequestMock();
  14. const res = createResponseMock();
  15. const route = createRouteMock();
  16. const throwable = v => () => new RequestContext(v, req, res, route);
  17. const error = v =>
  18. format(
  19. 'The parameter "container" of RequestContext.constructor ' +
  20. 'must be an instance of ServiceContainer, but %s was given.',
  21. v,
  22. );
  23. expect(throwable('str')).to.throw(error('"str"'));
  24. expect(throwable('')).to.throw(error('""'));
  25. expect(throwable(10)).to.throw(error('10'));
  26. expect(throwable(0)).to.throw(error('0'));
  27. expect(throwable(true)).to.throw(error('true'));
  28. expect(throwable(false)).to.throw(error('false'));
  29. expect(throwable(null)).to.throw(error('null'));
  30. expect(throwable({})).to.throw(error('Object'));
  31. expect(throwable([])).to.throw(error('Array'));
  32. expect(throwable(undefined)).to.throw(error('undefined'));
  33. throwable(new ServiceContainer())();
  34. });
  35. it('requires the parameter "request" to be an IncomingMessage instance', function () {
  36. const res = createResponseMock();
  37. const route = createRouteMock();
  38. const cont = new ServiceContainer();
  39. const throwable = v => () => new RequestContext(cont, v, res, route);
  40. const error = v =>
  41. format(
  42. 'The parameter "request" of RequestContext.constructor ' +
  43. 'must be an instance of IncomingMessage, but %s was given.',
  44. v,
  45. );
  46. expect(throwable('str')).to.throw(error('"str"'));
  47. expect(throwable('')).to.throw(error('""'));
  48. expect(throwable(10)).to.throw(error('10'));
  49. expect(throwable(0)).to.throw(error('0'));
  50. expect(throwable(true)).to.throw(error('true'));
  51. expect(throwable(false)).to.throw(error('false'));
  52. expect(throwable(null)).to.throw(error('null'));
  53. expect(throwable({})).to.throw(error('Object'));
  54. expect(throwable([])).to.throw(error('Array'));
  55. expect(throwable(undefined)).to.throw(error('undefined'));
  56. throwable(createRequestMock())();
  57. });
  58. it('requires the parameter "response" to be a ServerResponse instance', function () {
  59. const req = createRequestMock();
  60. const route = createRouteMock();
  61. const cont = new ServiceContainer();
  62. const throwable = v => () => new RequestContext(cont, req, v, route);
  63. const error = v =>
  64. format(
  65. 'The parameter "response" of RequestContext.constructor ' +
  66. 'must be an instance of ServerResponse, but %s was given.',
  67. v,
  68. );
  69. expect(throwable('str')).to.throw(error('"str"'));
  70. expect(throwable('')).to.throw(error('""'));
  71. expect(throwable(10)).to.throw(error('10'));
  72. expect(throwable(0)).to.throw(error('0'));
  73. expect(throwable(true)).to.throw(error('true'));
  74. expect(throwable(false)).to.throw(error('false'));
  75. expect(throwable(null)).to.throw(error('null'));
  76. expect(throwable({})).to.throw(error('Object'));
  77. expect(throwable([])).to.throw(error('Array'));
  78. expect(throwable(undefined)).to.throw(error('undefined'));
  79. throwable(createResponseMock())();
  80. });
  81. it('requires the parameter "route" to be a Route instance', function () {
  82. const req = createRequestMock();
  83. const res = createResponseMock();
  84. const cont = new ServiceContainer();
  85. const throwable = v => () => new RequestContext(cont, req, res, v);
  86. const error = v =>
  87. format(
  88. 'The parameter "route" of RequestContext.constructor ' +
  89. 'must be an instance of Route, but %s was given.',
  90. v,
  91. );
  92. expect(throwable('str')).to.throw(error('"str"'));
  93. expect(throwable('')).to.throw(error('""'));
  94. expect(throwable(10)).to.throw(error('10'));
  95. expect(throwable(0)).to.throw(error('0'));
  96. expect(throwable(true)).to.throw(error('true'));
  97. expect(throwable(false)).to.throw(error('false'));
  98. expect(throwable(null)).to.throw(error('null'));
  99. expect(throwable({})).to.throw(error('Object'));
  100. expect(throwable([])).to.throw(error('Array'));
  101. expect(throwable(undefined)).to.throw(error('undefined'));
  102. throwable(createRouteMock())();
  103. });
  104. it('sets properties from given arguments', function () {
  105. const req = createRequestMock();
  106. const res = createResponseMock();
  107. const route = createRouteMock();
  108. const cont = new ServiceContainer();
  109. const ctx = new RequestContext(cont, req, res, route);
  110. expect(ctx.container).to.be.eq(cont);
  111. expect(ctx.request).to.be.eq(req);
  112. expect(ctx.response).to.be.eq(res);
  113. });
  114. });
  115. describe('method', function () {
  116. it('returns the method name in upper case', function () {
  117. const req = createRequestMock({method: 'post'});
  118. const res = createResponseMock();
  119. const route = createRouteMock();
  120. const cont = new ServiceContainer();
  121. const ctx = new RequestContext(cont, req, res, route);
  122. expect(ctx.method).to.be.eq('POST');
  123. });
  124. });
  125. describe('path', function () {
  126. it('returns the request pathname with the query string', function () {
  127. const req = createRequestMock({path: '/pathname?foo=bar'});
  128. const res = createResponseMock();
  129. const route = createRouteMock();
  130. const cont = new ServiceContainer();
  131. const ctx = new RequestContext(cont, req, res, route);
  132. expect(req.url).to.be.eq('/pathname?foo=bar');
  133. expect(ctx.path).to.be.eq('/pathname?foo=bar');
  134. });
  135. });
  136. describe('pathname', function () {
  137. it('returns the request pathname without the query string', function () {
  138. const req = createRequestMock({path: '/pathname?foo=bar'});
  139. const res = createResponseMock();
  140. const route = createRouteMock();
  141. const cont = new ServiceContainer();
  142. const ctx = new RequestContext(cont, req, res, route);
  143. expect(req.url).to.be.eq('/pathname?foo=bar');
  144. expect(ctx.pathname).to.be.eq('/pathname');
  145. });
  146. it('sets the cache to the "_pathname" property and uses is for next accesses', function () {
  147. const req = createRequestMock({path: '/pathname'});
  148. const res = createResponseMock();
  149. const route = createRouteMock();
  150. const cont = new ServiceContainer();
  151. const ctx = new RequestContext(cont, req, res, route);
  152. expect(ctx._pathname).to.be.undefined;
  153. expect(ctx.pathname).to.be.eq('/pathname');
  154. expect(ctx._pathname).to.be.eq('/pathname');
  155. ctx._pathname = '/overridden';
  156. expect(ctx.pathname).to.be.eq('/overridden');
  157. });
  158. });
  159. describe('state', function () {
  160. it('has an empty object by default', function () {
  161. const req = createRequestMock({path: '/pathname'});
  162. const res = createResponseMock();
  163. const route = createRouteMock();
  164. const cont = new ServiceContainer();
  165. const ctx = new RequestContext(cont, req, res, route);
  166. expect(ctx.state).to.be.eql({});
  167. });
  168. });
  169. });