request.spec.tsx 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  2. import {Request} from 'sentry/components/events/interfaces/request';
  3. import {EntryRequest, EntryType} from 'sentry/types/event';
  4. describe('Request entry', function () {
  5. it('display redacted data', async function () {
  6. const event = {
  7. ...TestStubs.Event(),
  8. entries: [
  9. {
  10. type: 'request',
  11. data: {
  12. env: {
  13. DOCUMENT_ROOT: '',
  14. REMOTE_ADDR: '',
  15. SERVER_NAME: '',
  16. SERVER_PORT: '',
  17. },
  18. method: 'POST',
  19. query: [],
  20. url: '/Home/PostIndex',
  21. inferredContentType: null,
  22. fragment: null,
  23. headers: [],
  24. cookies: [],
  25. data: [
  26. {
  27. a: '',
  28. c: [
  29. {
  30. d: '',
  31. f: '',
  32. },
  33. ],
  34. },
  35. ],
  36. },
  37. },
  38. ],
  39. _meta: {
  40. entries: {
  41. 0: {
  42. data: {
  43. '': null,
  44. method: null,
  45. url: null,
  46. query: null,
  47. data: {
  48. a: {
  49. '': {
  50. rem: [['project:3', 's', 0, 0]],
  51. len: 1,
  52. chunks: [
  53. {
  54. type: 'redaction',
  55. text: '',
  56. rule_id: 'project:3',
  57. remark: 's',
  58. },
  59. ],
  60. },
  61. },
  62. c: {
  63. 0: {
  64. d: {
  65. '': {
  66. rem: [['project:3', 's', 0, 0]],
  67. len: 1,
  68. chunks: [
  69. {
  70. type: 'redaction',
  71. text: '',
  72. rule_id: 'project:3',
  73. remark: 's',
  74. },
  75. ],
  76. },
  77. },
  78. f: {
  79. '': {
  80. rem: [['project:3', 's', 0, 0]],
  81. len: 1,
  82. chunks: [
  83. {
  84. type: 'redaction',
  85. text: '',
  86. rule_id: 'project:3',
  87. remark: 's',
  88. },
  89. ],
  90. },
  91. },
  92. },
  93. },
  94. },
  95. env: {
  96. DOCUMENT_ROOT: {
  97. '': {
  98. rem: [['project:3', 's', 0, 0]],
  99. len: 78,
  100. chunks: [
  101. {
  102. type: 'redaction',
  103. text: '',
  104. rule_id: 'project:3',
  105. remark: 's',
  106. },
  107. ],
  108. },
  109. },
  110. REMOTE_ADDR: {
  111. '': {
  112. rem: [['project:3', 's', 0, 0]],
  113. len: 3,
  114. chunks: [
  115. {
  116. type: 'redaction',
  117. text: '',
  118. rule_id: 'project:3',
  119. remark: 's',
  120. },
  121. ],
  122. },
  123. },
  124. SERVER_NAME: {
  125. '': {
  126. rem: [['project:3', 's', 0, 0]],
  127. len: 7,
  128. chunks: [
  129. {
  130. type: 'redaction',
  131. text: '',
  132. rule_id: 'project:3',
  133. remark: 's',
  134. },
  135. ],
  136. },
  137. },
  138. SERVER_PORT: {
  139. '': {
  140. rem: [['project:3', 's', 0, 0]],
  141. len: 5,
  142. chunks: [
  143. {
  144. type: 'redaction',
  145. text: '',
  146. rule_id: 'project:3',
  147. remark: 's',
  148. },
  149. ],
  150. },
  151. },
  152. },
  153. },
  154. },
  155. },
  156. },
  157. };
  158. render(<Request event={event} data={event.entries[0].data} />);
  159. expect(screen.getAllByText(/redacted/)).toHaveLength(5);
  160. userEvent.click(await screen.findByLabelText('Expand'));
  161. expect(screen.getAllByText(/redacted/)).toHaveLength(7);
  162. userEvent.hover(screen.getAllByText(/redacted/)[0]);
  163. expect(
  164. await screen.findByText('Replaced because of PII rule "project:3"')
  165. ).toBeInTheDocument(); // tooltip description
  166. });
  167. describe('getBodySection', function () {
  168. it('should return plain-text when given unrecognized inferred Content-Type', function () {
  169. const data: EntryRequest['data'] = {
  170. query: [],
  171. data: 'helloworld',
  172. headers: [],
  173. cookies: [],
  174. env: {},
  175. inferredContentType: null,
  176. method: 'POST',
  177. url: '/Home/PostIndex',
  178. fragment: null,
  179. };
  180. const event = {
  181. ...TestStubs.Event(),
  182. entries: [
  183. {
  184. type: EntryType.REQUEST,
  185. data,
  186. },
  187. ],
  188. };
  189. render(<Request event={event} data={event.entries[0].data} />);
  190. expect(
  191. screen.getByTestId('rich-http-content-body-section-pre')
  192. ).toBeInTheDocument();
  193. });
  194. it('should return a KeyValueList element when inferred Content-Type is x-www-form-urlencoded', function () {
  195. const data: EntryRequest['data'] = {
  196. query: [],
  197. data: {foo: ['bar'], bar: ['baz']},
  198. headers: [],
  199. cookies: [],
  200. env: {},
  201. inferredContentType: 'application/x-www-form-urlencoded',
  202. method: 'POST',
  203. url: '/Home/PostIndex',
  204. fragment: null,
  205. };
  206. const event = {
  207. ...TestStubs.Event(),
  208. entries: [
  209. {
  210. type: EntryType.REQUEST,
  211. data,
  212. },
  213. ],
  214. };
  215. render(<Request event={event} data={event.entries[0].data} />);
  216. expect(
  217. screen.getByTestId('rich-http-content-body-key-value-list')
  218. ).toBeInTheDocument();
  219. });
  220. it('should return a ContextData element when inferred Content-Type is application/json', function () {
  221. const data: EntryRequest['data'] = {
  222. query: [],
  223. data: {foo: 'bar'},
  224. headers: [],
  225. cookies: [],
  226. env: {},
  227. inferredContentType: 'application/json',
  228. method: 'POST',
  229. url: '/Home/PostIndex',
  230. fragment: null,
  231. };
  232. const event = {
  233. ...TestStubs.Event(),
  234. entries: [
  235. {
  236. type: EntryType.REQUEST,
  237. data,
  238. },
  239. ],
  240. };
  241. render(<Request event={event} data={event.entries[0].data} />);
  242. expect(
  243. screen.getByTestId('rich-http-content-body-context-data')
  244. ).toBeInTheDocument();
  245. });
  246. it('should not blow up in a malformed uri', function () {
  247. // > decodeURIComponent('a%AFc')
  248. // URIError: URI malformed
  249. const data: EntryRequest['data'] = {
  250. query: 'a%AFc',
  251. data: '',
  252. headers: [],
  253. cookies: [],
  254. env: {},
  255. method: 'POST',
  256. url: '/Home/PostIndex',
  257. fragment: null,
  258. };
  259. const event = {
  260. ...TestStubs.Event(),
  261. entries: [
  262. {
  263. type: EntryType.REQUEST,
  264. data,
  265. },
  266. ],
  267. };
  268. expect(() =>
  269. render(<Request event={event} data={event.entries[0].data} />)
  270. ).not.toThrow();
  271. });
  272. it("should not cause an invariant violation if data.data isn't a string", function () {
  273. const data: EntryRequest['data'] = {
  274. query: [],
  275. data: [{foo: 'bar', baz: 1}],
  276. headers: [],
  277. cookies: [],
  278. env: {},
  279. method: 'POST',
  280. url: '/Home/PostIndex',
  281. fragment: null,
  282. };
  283. const event = {
  284. ...TestStubs.Event(),
  285. entries: [
  286. {
  287. type: EntryType.REQUEST,
  288. data,
  289. },
  290. ],
  291. };
  292. expect(() =>
  293. render(<Request event={event} data={event.entries[0].data} />)
  294. ).not.toThrow();
  295. });
  296. });
  297. });