request.spec.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  3. import {textWithMarkupMatcher} from 'sentry-test/utils';
  4. import {Request} from 'sentry/components/events/interfaces/request';
  5. import {EntryRequest, EntryType} from 'sentry/types/event';
  6. import {OrganizationContext} from 'sentry/views/organizationContext';
  7. import {RouteContext} from 'sentry/views/routeContext';
  8. describe('Request entry', function () {
  9. const {organization, router} = initializeOrg({
  10. ...initializeOrg(),
  11. organization: {
  12. ...initializeOrg().organization,
  13. relayPiiConfig: JSON.stringify(TestStubs.DataScrubbingRelayPiiConfig()),
  14. },
  15. });
  16. it('display redacted data', async function () {
  17. const event = {
  18. ...TestStubs.Event(),
  19. entries: [
  20. {
  21. type: 'request',
  22. data: {
  23. env: {
  24. DOCUMENT_ROOT: '',
  25. REMOTE_ADDR: '',
  26. SERVER_NAME: '',
  27. SERVER_PORT: '',
  28. },
  29. method: 'POST',
  30. query: [],
  31. url: '/Home/PostIndex',
  32. inferredContentType: null,
  33. fragment: null,
  34. headers: [],
  35. cookies: [],
  36. data: [
  37. {
  38. a: '',
  39. c: [
  40. {
  41. d: '',
  42. f: '',
  43. },
  44. ],
  45. },
  46. ],
  47. },
  48. },
  49. ],
  50. _meta: {
  51. entries: {
  52. 0: {
  53. data: {
  54. '': null,
  55. method: null,
  56. url: null,
  57. query: null,
  58. data: {
  59. a: {
  60. '': {
  61. rem: [['organization:0', 's', 0, 0]],
  62. len: 1,
  63. chunks: [
  64. {
  65. type: 'redaction',
  66. text: '',
  67. rule_id: 'organization:0',
  68. remark: 's',
  69. },
  70. ],
  71. },
  72. },
  73. c: {
  74. 0: {
  75. d: {
  76. '': {
  77. rem: [['organization:0', 's', 0, 0]],
  78. len: 1,
  79. chunks: [
  80. {
  81. type: 'redaction',
  82. text: '',
  83. rule_id: 'organization:0',
  84. remark: 's',
  85. },
  86. ],
  87. },
  88. },
  89. f: {
  90. '': {
  91. rem: [['organization:0', 's', 0, 0]],
  92. len: 1,
  93. chunks: [
  94. {
  95. type: 'redaction',
  96. text: '',
  97. rule_id: 'organization:0',
  98. remark: 's',
  99. },
  100. ],
  101. },
  102. },
  103. },
  104. },
  105. },
  106. env: {
  107. DOCUMENT_ROOT: {
  108. '': {
  109. rem: [['organization:0', 's', 0, 0]],
  110. len: 78,
  111. chunks: [
  112. {
  113. type: 'redaction',
  114. text: '',
  115. rule_id: 'organization:0',
  116. remark: 's',
  117. },
  118. ],
  119. },
  120. },
  121. REMOTE_ADDR: {
  122. '': {
  123. rem: [['organization:0', 's', 0, 0]],
  124. len: 3,
  125. chunks: [
  126. {
  127. type: 'redaction',
  128. text: '',
  129. rule_id: 'organization:0',
  130. remark: 's',
  131. },
  132. ],
  133. },
  134. },
  135. SERVER_NAME: {
  136. '': {
  137. rem: [['organization:0', 's', 0, 0]],
  138. len: 7,
  139. chunks: [
  140. {
  141. type: 'redaction',
  142. text: '',
  143. rule_id: 'organization:0',
  144. remark: 's',
  145. },
  146. ],
  147. },
  148. },
  149. SERVER_PORT: {
  150. '': {
  151. rem: [['organization:0', 's', 0, 0]],
  152. len: 5,
  153. chunks: [
  154. {
  155. type: 'redaction',
  156. text: '',
  157. rule_id: 'organization:0',
  158. remark: 's',
  159. },
  160. ],
  161. },
  162. },
  163. },
  164. },
  165. },
  166. },
  167. },
  168. };
  169. render(
  170. <OrganizationContext.Provider value={organization}>
  171. <RouteContext.Provider
  172. value={{
  173. router,
  174. location: router.location,
  175. params: {},
  176. routes: [],
  177. }}
  178. >
  179. <Request event={event} data={event.entries[0].data} />
  180. </RouteContext.Provider>
  181. </OrganizationContext.Provider>
  182. );
  183. expect(screen.getAllByText(/redacted/)).toHaveLength(5);
  184. userEvent.click(await screen.findByLabelText('Expand'));
  185. expect(screen.getAllByText(/redacted/)).toHaveLength(7);
  186. userEvent.hover(screen.getAllByText(/redacted/)[0]);
  187. expect(
  188. await screen.findByText(
  189. textWithMarkupMatcher(
  190. 'Replaced because of the PII rule [Replace] [Password fields] with [Scrubbed] from [password] in the settings of the organization org-slug'
  191. )
  192. )
  193. ).toBeInTheDocument(); // tooltip description
  194. });
  195. describe('getBodySection', function () {
  196. it('should return plain-text when given unrecognized inferred Content-Type', function () {
  197. const data: EntryRequest['data'] = {
  198. query: [],
  199. data: 'helloworld',
  200. headers: [],
  201. cookies: [],
  202. env: {},
  203. inferredContentType: null,
  204. method: 'POST',
  205. url: '/Home/PostIndex',
  206. fragment: null,
  207. };
  208. const event = {
  209. ...TestStubs.Event(),
  210. entries: [
  211. {
  212. type: EntryType.REQUEST,
  213. data,
  214. },
  215. ],
  216. };
  217. render(
  218. <OrganizationContext.Provider value={organization}>
  219. <RouteContext.Provider
  220. value={{
  221. router,
  222. location: router.location,
  223. params: {},
  224. routes: [],
  225. }}
  226. >
  227. <Request event={event} data={event.entries[0].data} />
  228. </RouteContext.Provider>
  229. </OrganizationContext.Provider>
  230. );
  231. expect(
  232. screen.getByTestId('rich-http-content-body-section-pre')
  233. ).toBeInTheDocument();
  234. });
  235. it('should return a KeyValueList element when inferred Content-Type is x-www-form-urlencoded', function () {
  236. const data: EntryRequest['data'] = {
  237. query: [],
  238. data: {foo: ['bar'], bar: ['baz']},
  239. headers: [],
  240. cookies: [],
  241. env: {},
  242. inferredContentType: 'application/x-www-form-urlencoded',
  243. method: 'POST',
  244. url: '/Home/PostIndex',
  245. fragment: null,
  246. };
  247. const event = {
  248. ...TestStubs.Event(),
  249. entries: [
  250. {
  251. type: EntryType.REQUEST,
  252. data,
  253. },
  254. ],
  255. };
  256. render(
  257. <OrganizationContext.Provider value={organization}>
  258. <RouteContext.Provider
  259. value={{
  260. router,
  261. location: router.location,
  262. params: {},
  263. routes: [],
  264. }}
  265. >
  266. <Request event={event} data={event.entries[0].data} />
  267. </RouteContext.Provider>
  268. </OrganizationContext.Provider>
  269. );
  270. expect(
  271. screen.getByTestId('rich-http-content-body-key-value-list')
  272. ).toBeInTheDocument();
  273. });
  274. it('should return a ContextData element when inferred Content-Type is application/json', function () {
  275. const data: EntryRequest['data'] = {
  276. query: [],
  277. data: {foo: 'bar'},
  278. headers: [],
  279. cookies: [],
  280. env: {},
  281. inferredContentType: 'application/json',
  282. method: 'POST',
  283. url: '/Home/PostIndex',
  284. fragment: null,
  285. };
  286. const event = {
  287. ...TestStubs.Event(),
  288. entries: [
  289. {
  290. type: EntryType.REQUEST,
  291. data,
  292. },
  293. ],
  294. };
  295. render(
  296. <OrganizationContext.Provider value={organization}>
  297. <RouteContext.Provider
  298. value={{
  299. router,
  300. location: router.location,
  301. params: {},
  302. routes: [],
  303. }}
  304. >
  305. <Request event={event} data={event.entries[0].data} />
  306. </RouteContext.Provider>
  307. </OrganizationContext.Provider>
  308. );
  309. expect(
  310. screen.getByTestId('rich-http-content-body-context-data')
  311. ).toBeInTheDocument();
  312. });
  313. it('should not blow up in a malformed uri', function () {
  314. // > decodeURIComponent('a%AFc')
  315. // URIError: URI malformed
  316. const data: EntryRequest['data'] = {
  317. query: 'a%AFc',
  318. data: '',
  319. headers: [],
  320. cookies: [],
  321. env: {},
  322. method: 'POST',
  323. url: '/Home/PostIndex',
  324. fragment: null,
  325. };
  326. const event = {
  327. ...TestStubs.Event(),
  328. entries: [
  329. {
  330. type: EntryType.REQUEST,
  331. data,
  332. },
  333. ],
  334. };
  335. expect(() =>
  336. render(
  337. <OrganizationContext.Provider value={organization}>
  338. <RouteContext.Provider
  339. value={{
  340. router,
  341. location: router.location,
  342. params: {},
  343. routes: [],
  344. }}
  345. >
  346. <Request event={event} data={event.entries[0].data} />
  347. </RouteContext.Provider>
  348. </OrganizationContext.Provider>
  349. )
  350. ).not.toThrow();
  351. });
  352. it("should not cause an invariant violation if data.data isn't a string", function () {
  353. const data: EntryRequest['data'] = {
  354. query: [],
  355. data: [{foo: 'bar', baz: 1}],
  356. headers: [],
  357. cookies: [],
  358. env: {},
  359. method: 'POST',
  360. url: '/Home/PostIndex',
  361. fragment: null,
  362. };
  363. const event = {
  364. ...TestStubs.Event(),
  365. entries: [
  366. {
  367. type: EntryType.REQUEST,
  368. data,
  369. },
  370. ],
  371. };
  372. expect(() =>
  373. render(
  374. <OrganizationContext.Provider value={organization}>
  375. <RouteContext.Provider
  376. value={{
  377. router,
  378. location: router.location,
  379. params: {},
  380. routes: [],
  381. }}
  382. >
  383. <Request event={event} data={event.entries[0].data} />
  384. </RouteContext.Provider>
  385. </OrganizationContext.Provider>
  386. )
  387. ).not.toThrow();
  388. });
  389. });
  390. });