@@ -8,16 +8,24 @@ const invalidTargets = new Set(['_parent', '_top'])
88 */
99export function handleInvalidEventTarget ( e : Event & { target : HTMLFormElement | HTMLAnchorElement } ) {
1010 let targetValue = e . target . target
11+ let targetSet = e . target . hasAttribute ( 'target' )
1112
1213 if ( invalidTargets . has ( e . target . target ) ) {
1314 e . target . target = ''
1415 }
1516
16- const { getAttribute, setAttribute } = e . target
17+ const { getAttribute, setAttribute, removeAttribute } = e . target
1718 const targetDescriptor = Object . getOwnPropertyDescriptor ( e . target , 'target' )
1819
1920 e . target . getAttribute = function ( k ) {
2021 if ( k === 'target' ) {
22+ // https://github.com/cypress-io/cypress/issues/17512
23+ // When the target attribute doesn't exist, it should return null.
24+ // @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute#non-existing_attributes
25+ if ( ! targetSet ) {
26+ return null
27+ }
28+
2129 return targetValue
2230 }
2331
@@ -26,6 +34,7 @@ export function handleInvalidEventTarget (e: Event & {target: HTMLFormElement |
2634
2735 e . target . setAttribute = function ( k , v ) {
2836 if ( k === 'target' ) {
37+ targetSet = true
2938 targetValue = v
3039
3140 return $elements . callNativeMethod ( this , 'setAttribute' , 'cyTarget' , v )
@@ -34,6 +43,16 @@ export function handleInvalidEventTarget (e: Event & {target: HTMLFormElement |
3443 return setAttribute . call ( this , k , v )
3544 }
3645
46+ e . target . removeAttribute = function ( k ) {
47+ if ( k === 'target' ) {
48+ targetSet = false
49+ targetValue = ''
50+
51+ // We're not using `$elements.callNativeMethod` here because it disallows `removeAttribute`.
52+ return removeAttribute . call ( this , k )
53+ }
54+ }
55+
3756 if ( ! targetDescriptor ) {
3857 Object . defineProperty ( e . target , 'target' , {
3958 configurable : false ,
0 commit comments