@@ -536,6 +536,169 @@ describe('integration', function () {
536536 ) ;
537537 } ) ;
538538
539+ it ( 'should record consecutive keypress events into a single "input" breadcrumb' , function ( done ) {
540+ var iframe = this . iframe ;
541+
542+ iframeExecute ( iframe , done ,
543+ function ( ) {
544+ // keypress events are debounced 1000ms - wait until
545+ // the debounce finishes
546+ setTimeout ( done , 1001 ) ;
547+
548+ // some browsers trigger onpopstate for load / reset breadcrumb state
549+ Raven . _breadcrumbs = [ ] ;
550+
551+ // keypress <input/> twice
552+ var keypress1 = document . createEvent ( 'MouseEvent' ) ;
553+ keypress1 . initMouseEvent (
554+ "keypress" ,
555+ true /* bubble */ ,
556+ true /* cancelable */ ,
557+ window ,
558+ null ,
559+ 0 , 0 , 0 , 0 , /* coordinates */
560+ false , false , false , false , /* modifier keys */
561+ 0 /*left*/ ,
562+ null
563+ ) ;
564+
565+ var keypress2 = document . createEvent ( 'MouseEvent' ) ;
566+ keypress2 . initMouseEvent (
567+ "keypress" ,
568+ true /* bubble */ ,
569+ true /* cancelable */ ,
570+ window ,
571+ null ,
572+ 0 , 0 , 0 , 0 , /* coordinates */
573+ false , false , false , false , /* modifier keys */
574+ 0 /*left*/ ,
575+ null
576+ ) ;
577+
578+ var input = document . getElementsByTagName ( 'input' ) [ 0 ] ;
579+ input . dispatchEvent ( keypress1 ) ;
580+ input . dispatchEvent ( keypress2 ) ;
581+ } ,
582+ function ( ) {
583+ var Raven = iframe . contentWindow . Raven ,
584+ breadcrumbs = Raven . _breadcrumbs ;
585+
586+ assert . equal ( breadcrumbs . length , 1 ) ;
587+
588+ assert . equal ( breadcrumbs [ 0 ] . type , 'ui_event' ) ;
589+ // NOTE: attributes re-ordered. should this be expected?
590+ assert . equal ( breadcrumbs [ 0 ] . data . target , 'body > form#foo-form > input[name="foo"][placeholder="lol"]' ) ;
591+ assert . equal ( breadcrumbs [ 0 ] . data . type , 'input' ) ;
592+ }
593+ ) ;
594+ } ) ;
595+
596+ it ( 'should flush keypress breadcrumbs when an error is thrown' , function ( done ) {
597+ var iframe = this . iframe ;
598+
599+ iframeExecute ( iframe , done ,
600+ function ( ) {
601+ setTimeout ( done ) ;
602+
603+ // some browsers trigger onpopstate for load / reset breadcrumb state
604+ Raven . _breadcrumbs = [ ] ;
605+
606+ // click <input/>
607+ var evt = document . createEvent ( 'MouseEvent' ) ;
608+ evt . initMouseEvent (
609+ "keypress" ,
610+ true /* bubble */ ,
611+ true /* cancelable */ ,
612+ window ,
613+ null ,
614+ 0 , 0 , 0 , 0 , /* coordinates */
615+ false , false , false , false , /* modifier keys */
616+ 0 /*left*/ ,
617+ null
618+ ) ;
619+
620+ var input = document . getElementsByTagName ( 'input' ) [ 0 ] ;
621+ input . dispatchEvent ( evt ) ;
622+
623+ foo ( ) ; // throw exception
624+ } ,
625+ function ( ) {
626+ var Raven = iframe . contentWindow . Raven ,
627+ breadcrumbs = Raven . _breadcrumbs ;
628+
629+ // 2 breadcrumbs: `ui_event`, then `error`
630+ assert . equal ( breadcrumbs . length , 2 ) ;
631+
632+ assert . equal ( breadcrumbs [ 0 ] . type , 'ui_event' ) ;
633+ // NOTE: attributes re-ordered. should this be expected?
634+ assert . equal ( breadcrumbs [ 0 ] . data . target , 'body > form#foo-form > input[name="foo"][placeholder="lol"]' ) ;
635+ assert . equal ( breadcrumbs [ 0 ] . data . type , 'input' ) ;
636+ }
637+ ) ;
638+ } ) ;
639+
640+ it ( 'should flush keypress breadcrumb when input event occurs immediately after' , function ( done ) {
641+ var iframe = this . iframe ;
642+
643+ iframeExecute ( iframe , done ,
644+ function ( ) {
645+ setTimeout ( done ) ;
646+
647+ // some browsers trigger onpopstate for load / reset breadcrumb state
648+ Raven . _breadcrumbs = [ ] ;
649+
650+ // keypress <input/>
651+ var keypressEvent = document . createEvent ( 'MouseEvent' ) ;
652+ keypressEvent . initMouseEvent (
653+ "keypress" ,
654+ true /* bubble */ ,
655+ true /* cancelable */ ,
656+ window ,
657+ null ,
658+ 0 , 0 , 0 , 0 , /* coordinates */
659+ false , false , false , false , /* modifier keys */
660+ 0 /*left*/ ,
661+ null
662+ ) ;
663+
664+ // click <input/>
665+ var clickEvent = document . createEvent ( 'MouseEvent' ) ;
666+ clickEvent . initMouseEvent (
667+ "click" ,
668+ true /* bubble */ ,
669+ true /* cancelable */ ,
670+ window ,
671+ null ,
672+ 0 , 0 , 0 , 0 , /* coordinates */
673+ false , false , false , false , /* modifier keys */
674+ 0 /*left*/ ,
675+ null
676+ ) ;
677+
678+ var input = document . getElementsByTagName ( 'input' ) [ 0 ] ;
679+ input . dispatchEvent ( keypressEvent ) ;
680+ input . dispatchEvent ( clickEvent ) ;
681+ } ,
682+ function ( ) {
683+ var Raven = iframe . contentWindow . Raven ,
684+ breadcrumbs = Raven . _breadcrumbs ;
685+
686+ // 2x `ui_event`
687+ assert . equal ( breadcrumbs . length , 2 ) ;
688+
689+ assert . equal ( breadcrumbs [ 0 ] . type , 'ui_event' ) ;
690+ // NOTE: attributes re-ordered. should this be expected?
691+ assert . equal ( breadcrumbs [ 0 ] . data . target , 'body > form#foo-form > input[name="foo"][placeholder="lol"]' ) ;
692+ assert . equal ( breadcrumbs [ 0 ] . data . type , 'input' ) ;
693+
694+ assert . equal ( breadcrumbs [ 1 ] . type , 'ui_event' ) ;
695+ // NOTE: attributes re-ordered. should this be expected?
696+ assert . equal ( breadcrumbs [ 1 ] . data . target , 'body > form#foo-form > input[name="foo"][placeholder="lol"]' ) ;
697+ assert . equal ( breadcrumbs [ 1 ] . data . type , 'click' ) ;
698+ }
699+ ) ;
700+ } ) ;
701+
539702 it ( 'should record history.[pushState|back] changes as navigation breadcrumbs' , function ( done ) {
540703 var iframe = this . iframe ;
541704
0 commit comments