mediawiki/extensions/DonationInterface: main (log #2466955)

sourcepatches

This run took 177 seconds.

From c83ec60c3005ae2fb7ef8ff4cc85823846266fa2 Mon Sep 17 00:00:00 2001
From: libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
Date: Wed, 6 May 2026 03:25:59 +0000
Subject: [PATCH] build: Updating dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

composer:
* mediawiki/mediawiki-codesniffer: 50.0.0 → 51.0.0

npm:
* eslint-config-wikimedia: 0.32.3 → 0.32.4

Change-Id: I1f9bec62f8f85923ee15d2d0c4203e0341f3ffce
---
 composer.json     |   2 +-
 package-lock.json | 557 ++++++++++++++++++----------------------------
 package.json      |   2 +-
 3 files changed, 217 insertions(+), 344 deletions(-)

diff --git a/composer.json b/composer.json
index 41e147c..f9750c5 100644
--- a/composer.json
+++ b/composer.json
@@ -34,7 +34,7 @@
 		"whichbrowser/parser": "^2.1"
 	},
 	"require-dev": {
-		"mediawiki/mediawiki-codesniffer": "50.0.0",
+		"mediawiki/mediawiki-codesniffer": "51.0.0",
 		"mediawiki/mediawiki-phan-config": "0.20.0",
 		"mediawiki/minus-x": "2.0.1",
 		"php-parallel-lint/php-console-highlighter": "1.0.0",
diff --git a/package-lock.json b/package-lock.json
index 93bd10c..bd127fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
 				"@wikimedia/codex": "2.4.0",
 				"@wikimedia/codex-icons": "2.4.0",
 				"babel-core": "^6.26.3",
-				"eslint-config-wikimedia": "0.32.3",
+				"eslint-config-wikimedia": "0.32.4",
 				"eslint-plugin-jest": "27.2.1",
 				"grunt": "1.6.2",
 				"grunt-banana-checker": "0.13.0",
@@ -1755,25 +1755,25 @@
 			}
 		},
 		"node_modules/@es-joy/jsdoccomment": {
-			"version": "0.76.0",
-			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz",
-			"integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==",
+			"version": "0.86.0",
+			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+			"integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
 			"dev": true,
 			"dependencies": {
 				"@types/estree": "^1.0.8",
-				"@typescript-eslint/types": "^8.46.0",
-				"comment-parser": "1.4.1",
-				"esquery": "^1.6.0",
-				"jsdoc-type-pratt-parser": "~6.10.0"
+				"@typescript-eslint/types": "^8.58.0",
+				"comment-parser": "1.4.6",
+				"esquery": "^1.7.0",
+				"jsdoc-type-pratt-parser": "~7.2.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			}
 		},
 		"node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
-			"version": "8.48.1",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
-			"integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
+			"version": "8.59.2",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
+			"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1811,9 +1811,9 @@
 			}
 		},
 		"node_modules/@eslint-community/regexpp": {
-			"version": "4.12.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
-			"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+			"version": "4.12.2",
+			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
 			"dev": true,
 			"engines": {
 				"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -2872,9 +2872,9 @@
 			"dev": true
 		},
 		"node_modules/@mdn/browser-compat-data": {
-			"version": "5.7.6",
-			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
-			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"version": "6.1.5",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-6.1.5.tgz",
+			"integrity": "sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==",
 			"dev": true
 		},
 		"node_modules/@nodelib/fs.scandir": {
@@ -3227,9 +3227,9 @@
 			}
 		},
 		"node_modules/@tootallnate/once": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
-			"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz",
+			"integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==",
 			"dev": true,
 			"engines": {
 				"node": ">= 10"
@@ -3871,9 +3871,9 @@
 			"dev": true
 		},
 		"node_modules/acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+			"version": "8.16.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+			"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
 			"dev": true,
 			"bin": {
 				"acorn": "bin/acorn"
@@ -4074,6 +4074,12 @@
 				"@mdn/browser-compat-data": "^5.6.19"
 			}
 		},
+		"node_modules/ast-metadata-inferer/node_modules/@mdn/browser-compat-data": {
+			"version": "5.7.6",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
+			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"dev": true
+		},
 		"node_modules/astral-regex": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
@@ -4909,9 +4915,9 @@
 			}
 		},
 		"node_modules/comment-parser": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
-			"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+			"version": "1.4.6",
+			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
+			"integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==",
 			"dev": true,
 			"engines": {
 				"node": ">= 12.0.0"
@@ -5578,13 +5584,13 @@
 			}
 		},
 		"node_modules/enhanced-resolve": {
-			"version": "5.18.3",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
-			"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+			"version": "5.21.0",
+			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+			"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
 			"dev": true,
 			"dependencies": {
 				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
+				"tapable": "^2.3.3"
 			},
 			"engines": {
 				"node": ">=10.13.0"
@@ -5798,51 +5804,52 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia": {
-			"version": "0.32.3",
-			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.3.tgz",
-			"integrity": "sha512-Ekz2/ozpCCjQl3VbC6dW7ChqoW7FRilLDxmJ+FJOZhIxxzZSZR5QqQOAGWSZAlG1ONkZbYV/TPwGLWZcrNxyaA==",
+			"version": "0.32.4",
+			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.4.tgz",
+			"integrity": "sha512-zcHJYss2vo8HK5PzkFuaV9mzaSGRuhA+jFGoQ4rNIwWz0usZsuQ2LYpkKxrbCVX1CbV0PzG+jJ6p0cLI+G37JQ==",
 			"dev": true,
 			"dependencies": {
 				"@stylistic/eslint-plugin": "^3.1.0",
-				"@typescript-eslint/eslint-plugin": "8.46.0",
-				"@typescript-eslint/parser": "8.46.0",
+				"@typescript-eslint/eslint-plugin": "8.54.0",
+				"@typescript-eslint/parser": "8.54.0",
 				"browserslist-config-wikimedia": "^0.7.0",
-				"eslint": "^8.57.0",
-				"eslint-plugin-compat": "^6.0.2",
+				"eslint-plugin-compat": "^6.1.0",
 				"eslint-plugin-es-x": "^8.7.0",
-				"eslint-plugin-jest": "^29.0.1",
-				"eslint-plugin-jsdoc": "61.3.0",
+				"eslint-plugin-jest": "^29.12.2",
+				"eslint-plugin-jsdoc": "^62.9.0",
 				"eslint-plugin-json-es": "^1.6.0",
-				"eslint-plugin-mediawiki": "^0.8.2",
+				"eslint-plugin-mediawiki": "^0.8.3",
 				"eslint-plugin-mocha": "^10.5.0",
-				"eslint-plugin-n": "^17.23.1",
-				"eslint-plugin-no-jquery": "^3.1.1",
-				"eslint-plugin-qunit": "^8.2.5",
-				"eslint-plugin-security": "^3.0.1",
+				"eslint-plugin-n": "^17.24.0",
+				"eslint-plugin-no-jquery": "^4.0.0",
+				"eslint-plugin-qunit": "^8.2.6",
+				"eslint-plugin-security": "^4.0.0",
 				"eslint-plugin-unicorn": "^56.0.1",
 				"eslint-plugin-vue": "^9.33.0",
-				"eslint-plugin-wdio": "^9.16.2",
+				"eslint-plugin-wdio": "9.23.0",
 				"eslint-plugin-yml": "^1.19.0"
 			},
 			"engines": {
 				"node": ">=20 <25"
+			},
+			"peerDependencies": {
+				"eslint": "^8.57.0"
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
-			"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+			"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/regexpp": "^4.10.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/type-utils": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"graphemer": "^1.4.0",
-				"ignore": "^7.0.0",
+				"@eslint-community/regexpp": "^4.12.2",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/type-utils": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"ignore": "^7.0.5",
 				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.1.0"
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5852,22 +5859,22 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
-				"@typescript-eslint/parser": "^8.46.0",
+				"@typescript-eslint/parser": "^8.54.0",
 				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
-			"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/parser": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+			"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"debug": "^4.3.4",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5881,16 +5888,15 @@
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
-			"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/project-service": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+			"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0"
+				"@typescript-eslint/tsconfig-utils": "^8.54.0",
+				"@typescript-eslint/types": "^8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5900,21 +5906,17 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/parser": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
-			"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/scope-manager": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+			"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5922,22 +5924,13 @@
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/project-service": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
-			"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/tsconfig-utils": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+			"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
 			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.0",
-				"@typescript-eslint/types": "^8.46.0",
-				"debug": "^4.3.4"
-			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
 			},
@@ -5949,14 +5942,17 @@
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
-			"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/type-utils": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+			"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"debug": "^4.4.3",
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5964,12 +5960,16 @@
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "^8.57.0 || ^9.0.0",
+				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
-			"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/types": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+			"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5977,40 +5977,45 @@
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/types": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
-			"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/typescript-estree": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+			"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
 			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/project-service": "8.54.0",
+				"@typescript-eslint/tsconfig-utils": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3",
+				"minimatch": "^9.0.5",
+				"semver": "^7.7.3",
+				"tinyglobby": "^0.2.15",
+				"ts-api-utils": "^2.4.0"
+			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
 			},
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
-			"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/utils": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+			"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/project-service": "8.46.0",
-				"@typescript-eslint/tsconfig-utils": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
+				"@eslint-community/eslint-utils": "^4.9.1",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6020,16 +6025,17 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
+				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
-			"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+			"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
+				"@typescript-eslint/types": "8.54.0",
 				"eslint-visitor-keys": "^4.2.1"
 			},
 			"engines": {
@@ -6041,9 +6047,9 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/brace-expansion": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
-			"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+			"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
 			"dev": true,
 			"dependencies": {
 				"balanced-match": "^1.0.0"
@@ -6078,141 +6084,6 @@
 				}
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/project-service": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz",
-			"integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.4",
-				"@typescript-eslint/types": "^8.46.4",
-				"debug": "^4.3.4"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz",
-			"integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/types": "8.46.4",
-				"@typescript-eslint/visitor-keys": "8.46.4"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz",
-			"integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==",
-			"dev": true,
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz",
-			"integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==",
-			"dev": true,
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz",
-			"integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/project-service": "8.46.4",
-				"@typescript-eslint/tsconfig-utils": "8.46.4",
-				"@typescript-eslint/types": "8.46.4",
-				"@typescript-eslint/visitor-keys": "8.46.4",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz",
-			"integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==",
-			"dev": true,
-			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.4",
-				"@typescript-eslint/types": "8.46.4",
-				"@typescript-eslint/typescript-estree": "8.46.4"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz",
-			"integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/types": "8.46.4",
-				"eslint-visitor-keys": "^4.2.1"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
 		"node_modules/eslint-config-wikimedia/node_modules/eslint-visitor-keys": {
 			"version": "4.2.1",
 			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
@@ -6250,9 +6121,9 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6262,15 +6133,14 @@
 			}
 		},
 		"node_modules/eslint-plugin-compat": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz",
-			"integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==",
+			"version": "6.2.1",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.2.1.tgz",
+			"integrity": "sha512-gLKqUH+lQcCL+HzsROUjBDvakc5Zaga51Y4ZAkPCXc41pzKBfyluqTr2j8zOx8QQQb7zyglu1LVoL5aSNWf2SQ==",
 			"dev": true,
 			"dependencies": {
-				"@mdn/browser-compat-data": "^5.5.35",
+				"@mdn/browser-compat-data": "^6.1.1",
 				"ast-metadata-inferer": "^0.8.1",
-				"browserslist": "^4.24.2",
-				"caniuse-lite": "^1.0.30001687",
+				"browserslist": "^4.25.2",
 				"find-up": "^5.0.0",
 				"globals": "^15.7.0",
 				"lodash.memoize": "^4.1.2",
@@ -6280,7 +6150,7 @@
 				"node": ">=18.x"
 			},
 			"peerDependencies": {
-				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-compat/node_modules/find-up": {
@@ -6342,9 +6212,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-compat/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6399,31 +6269,31 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc": {
-			"version": "61.3.0",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.3.0.tgz",
-			"integrity": "sha512-E4m/5J5lrasd63Z74q4CCZ4PFnywnnrcvA7zZ98802NPhrZKKTp5NH+XAT+afcjXp2ps2/OQF5gPSWCT2XFCJg==",
+			"version": "62.9.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+			"integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
 			"dev": true,
 			"dependencies": {
-				"@es-joy/jsdoccomment": "~0.76.0",
+				"@es-joy/jsdoccomment": "~0.86.0",
 				"@es-joy/resolve.exports": "1.2.0",
 				"are-docs-informative": "^0.0.2",
-				"comment-parser": "1.4.1",
+				"comment-parser": "1.4.6",
 				"debug": "^4.4.3",
 				"escape-string-regexp": "^4.0.0",
-				"espree": "^10.4.0",
-				"esquery": "^1.6.0",
+				"espree": "^11.2.0",
+				"esquery": "^1.7.0",
 				"html-entities": "^2.6.0",
 				"object-deep-merge": "^2.0.0",
 				"parse-imports-exports": "^0.2.4",
-				"semver": "^7.7.3",
+				"semver": "^7.7.4",
 				"spdx-expression-parse": "^4.0.0",
 				"to-valid-identifier": "^1.0.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"peerDependencies": {
-				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
@@ -6439,38 +6309,38 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": {
-			"version": "4.2.1",
-			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-			"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+			"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
 			"dev": true,
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/espree": {
-			"version": "10.4.0",
-			"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-			"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+			"version": "11.2.0",
+			"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+			"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
 			"dev": true,
 			"dependencies": {
-				"acorn": "^8.15.0",
+				"acorn": "^8.16.0",
 				"acorn-jsx": "^5.3.2",
-				"eslint-visitor-keys": "^4.2.1"
+				"eslint-visitor-keys": "^5.0.1"
 			},
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6493,9 +6363,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-mediawiki": {
-			"version": "0.8.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.2.tgz",
-			"integrity": "sha512-ydYrpkzm8IVVDQA96QPF3HnFd2xjkIEh7gixD2gvOqUbUZF0p36LtpWXOFAlPWAvHLePWbNNTD5ovd3d4hEtog==",
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.3.tgz",
+			"integrity": "sha512-RQKZd40C1taMDk5N9+aFLEBGBB95RNG7Gc54EsJ8pHsJu8//nIdpxNFWPtQz6RNxz6pZUXBnMCxzkMOLM3Mm1w==",
 			"dev": true,
 			"dependencies": {
 				"upath": "^2.0.1"
@@ -6549,9 +6419,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n": {
-			"version": "17.23.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
-			"integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+			"version": "17.24.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz",
+			"integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==",
 			"dev": true,
 			"dependencies": {
 				"@eslint-community/eslint-utils": "^4.5.0",
@@ -6623,9 +6493,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6635,31 +6505,34 @@
 			}
 		},
 		"node_modules/eslint-plugin-no-jquery": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-3.1.1.tgz",
-			"integrity": "sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-4.0.0.tgz",
+			"integrity": "sha512-ZR631D3qIQfgjKOAcgvYa5cB8xdTvFXAD5MbK5x5WltLSwFxmGnoaTXNtnptFU7py07ALrIe5dZRYncu4RD/Ug==",
 			"dev": true,
 			"peerDependencies": {
-				"eslint": ">=8.0.0"
+				"eslint": ">=8.0.0 <9.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-qunit": {
-			"version": "8.2.5",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.5.tgz",
-			"integrity": "sha512-qr7RJCYImKQjB+39q4q46i1l7p1V3joHzBE5CAYfxn5tfVFjrnjn/tw7q/kDyweU9kAIcLul0Dx/KWVUCb3BgA==",
+			"version": "8.2.6",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.6.tgz",
+			"integrity": "sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==",
 			"dev": true,
 			"dependencies": {
-				"eslint-utils": "^3.0.0",
+				"@eslint-community/eslint-utils": "^4.4.0",
 				"requireindex": "^1.2.0"
 			},
 			"engines": {
 				"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
+			},
+			"peerDependencies": {
+				"eslint": ">=8.38.0"
 			}
 		},
 		"node_modules/eslint-plugin-security": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
-			"integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-4.0.0.tgz",
+			"integrity": "sha512-tfuQT8K/Li1ZxhFzyD8wPIKtlzZxqBcPr9q0jFMQ77wWAbKBVEhaMPVQRTMTvCMUDhwBe5vPVqQPwAGk/ASfxQ==",
 			"dev": true,
 			"dependencies": {
 				"safe-regex": "^2.1.1"
@@ -6790,9 +6663,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-wdio": {
-			"version": "9.16.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
-			"integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
+			"version": "9.23.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.23.0.tgz",
+			"integrity": "sha512-8tcpupzp2Qmv+uSfhzeHi42LVA9PyjkpMBPclSIkPxBfXpj4fMrejwAHu1PROh1OmJN1VQcGQUTWvSzyRcV2vA==",
 			"dev": true,
 			"engines": {
 				"node": ">=18.20.0"
@@ -7123,9 +6996,9 @@
 			}
 		},
 		"node_modules/esquery": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
-			"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+			"version": "1.7.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
 			"dev": true,
 			"dependencies": {
 				"estraverse": "^5.1.0"
@@ -7625,9 +7498,9 @@
 			}
 		},
 		"node_modules/get-tsconfig": {
-			"version": "4.13.0",
-			"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
-			"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
+			"version": "4.14.0",
+			"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
+			"integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
 			"dev": true,
 			"dependencies": {
 				"resolve-pkg-maps": "^1.0.0"
@@ -10708,9 +10581,9 @@
 			}
 		},
 		"node_modules/jsdoc-type-pratt-parser": {
-			"version": "6.10.0",
-			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz",
-			"integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==",
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+			"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
 			"dev": true,
 			"engines": {
 				"node": ">=20.0.0"
@@ -13347,9 +13220,9 @@
 			"dev": true
 		},
 		"node_modules/tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+			"version": "2.3.3",
+			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+			"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
 			"dev": true,
 			"engines": {
 				"node": ">=6"
diff --git a/package.json b/package.json
index dcd2c0c..d684b0d 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
 		"@wikimedia/codex": "2.4.0",
 		"@wikimedia/codex-icons": "2.4.0",
 		"babel-core": "^6.26.3",
-		"eslint-config-wikimedia": "0.32.3",
+		"eslint-config-wikimedia": "0.32.4",
 		"eslint-plugin-jest": "27.2.1",
 		"grunt": "1.6.2",
 		"grunt-banana-checker": "0.13.0",
-- 
2.47.3

$ date
--- stdout ---
Wed May  6 03:23:10 UTC 2026

--- end ---
$ git clone file:///srv/git/mediawiki-extensions-DonationInterface.git /src/repo --depth=1 -b master
--- stderr ---
Cloning into '/src/repo'...
--- stdout ---

--- end ---
$ git config user.name libraryupgrader
--- stdout ---

--- end ---
$ git config user.email tools.libraryupgrader@tools.wmflabs.org
--- stdout ---

--- end ---
$ git submodule update --init
--- stdout ---

--- end ---
$ grr init
--- stdout ---
Installed commit-msg hook.

--- end ---
$ git show-ref refs/heads/master
--- stdout ---
7d1eae7cbdb01540aa3d964cca83a2e6ce6634b0 refs/heads/master

--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "@tootallnate/once": {
      "name": "@tootallnate/once",
      "severity": "low",
      "isDirect": false,
      "via": [
        {
          "source": 1113977,
          "name": "@tootallnate/once",
          "dependency": "@tootallnate/once",
          "title": "@tootallnate/once vulnerable to Incorrect Control Flow Scoping",
          "url": "https://github.com/advisories/GHSA-vpq2-c234-7xj6",
          "severity": "low",
          "cwe": [
            "CWE-705"
          ],
          "cvss": {
            "score": 3.3,
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L"
          },
          "range": "<3.0.1"
        }
      ],
      "effects": [
        "http-proxy-agent"
      ],
      "range": "<3.0.1",
      "nodes": [
        "node_modules/@tootallnate/once"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "babel-core": {
      "name": "babel-core",
      "severity": "critical",
      "isDirect": true,
      "via": [
        "babel-helpers",
        "babel-register",
        "babel-template",
        "babel-traverse",
        "json5"
      ],
      "effects": [
        "babel-register"
      ],
      "range": "5.8.20 - 7.0.0-beta.3",
      "nodes": [
        "node_modules/babel-core"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    },
    "babel-helpers": {
      "name": "babel-helpers",
      "severity": "critical",
      "isDirect": false,
      "via": [
        "babel-template"
      ],
      "effects": [],
      "range": "*",
      "nodes": [
        "node_modules/babel-helpers"
      ],
      "fixAvailable": true
    },
    "babel-register": {
      "name": "babel-register",
      "severity": "high",
      "isDirect": false,
      "via": [
        "babel-core"
      ],
      "effects": [
        "babel-core"
      ],
      "range": "*",
      "nodes": [
        "node_modules/babel-register"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    },
    "babel-template": {
      "name": "babel-template",
      "severity": "critical",
      "isDirect": false,
      "via": [
        "babel-traverse"
      ],
      "effects": [
        "babel-helpers"
      ],
      "range": "*",
      "nodes": [
        "node_modules/babel-template"
      ],
      "fixAvailable": true
    },
    "babel-traverse": {
      "name": "babel-traverse",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1117412,
          "name": "babel-traverse",
          "dependency": "babel-traverse",
          "title": "Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code",
          "url": "https://github.com/advisories/GHSA-67hx-6x53-jw92",
          "severity": "critical",
          "cwe": [
            "CWE-184",
            "CWE-697"
          ],
          "cvss": {
            "score": 9.3,
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
          },
          "range": "<7.23.2"
        }
      ],
      "effects": [
        "babel-core",
        "babel-template"
      ],
      "range": "*",
      "nodes": [
        "node_modules/babel-traverse"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    },
    "http-proxy-agent": {
      "name": "http-proxy-agent",
      "severity": "low",
      "isDirect": false,
      "via": [
        "@tootallnate/once"
      ],
      "effects": [
        "jsdom"
      ],
      "range": "4.0.1 - 5.0.0",
      "nodes": [
        "node_modules/http-proxy-agent"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "jest-environment-jsdom": {
      "name": "jest-environment-jsdom",
      "severity": "low",
      "isDirect": true,
      "via": [
        "jsdom"
      ],
      "effects": [],
      "range": "27.0.1 - 30.0.0-rc.1",
      "nodes": [
        "node_modules/jest-environment-jsdom"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "jsdom": {
      "name": "jsdom",
      "severity": "low",
      "isDirect": false,
      "via": [
        "http-proxy-agent"
      ],
      "effects": [
        "jest-environment-jsdom"
      ],
      "range": "16.6.0 - 22.1.0",
      "nodes": [
        "node_modules/jsdom"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "json5": {
      "name": "json5",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1096543,
          "name": "json5",
          "dependency": "json5",
          "title": "Prototype Pollution in JSON5 via Parse Method",
          "url": "https://github.com/advisories/GHSA-9c47-m6qq-7p4h",
          "severity": "high",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 7.1,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:H"
          },
          "range": "<1.0.2"
        }
      ],
      "effects": [
        "babel-core"
      ],
      "range": "<1.0.2",
      "nodes": [
        "node_modules/babel-core/node_modules/json5"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    }
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 4,
      "moderate": 0,
      "high": 2,
      "critical": 4,
      "total": 10
    },
    "dependencies": {
      "prod": 1,
      "dev": 1122,
      "optional": 3,
      "peer": 2,
      "peerOptional": 0,
      "total": 1122
    }
  }
}

--- end ---
$ /usr/bin/composer install
--- stderr ---
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
                                                      Updating dependencies
Lock file operations: 78 installs, 0 updates, 0 removals
  - Locking addshore/psr-6-mediawiki-bagostuff-adapter (0.1)
  - Locking amzn/login-and-pay-with-amazon-sdk-php (2.5.0)
  - Locking brick/math (0.14.8)
  - Locking brick/money (0.10.3)
  - Locking clio/clio (0.1.8)
  - Locking coderkungfu/php-queue (1.0.2)
  - Locking composer/ca-bundle (1.5.11)
  - Locking composer/pcre (3.3.2)
  - Locking composer/semver (3.4.4)
  - Locking composer/spdx-licenses (1.5.10)
  - Locking composer/xdebug-handler (3.0.5)
  - Locking corneltek/getoptionkit (2.7.3)
  - Locking danog/advanced-json-rpc (v3.2.3)
  - Locking dealerdirect/phpcodesniffer-composer-installer (v1.2.0)
  - Locking doctrine/deprecations (1.1.6)
  - Locking geoip2/geoip2 (v2.13.0)
  - Locking gr4vy/gr4vy-php (v0.27.0)
  - Locking guzzlehttp/guzzle (7.10.0)
  - Locking guzzlehttp/promises (2.3.0)
  - Locking guzzlehttp/psr7 (2.9.0)
  - Locking lcobucci/clock (3.3.1)
  - Locking lcobucci/jwt (4.3.0)
  - Locking maxmind-db/reader (v1.13.1)
  - Locking maxmind/minfraud (v1.23.0)
  - Locking maxmind/web-service-common (v0.9.0)
  - Locking mediawiki/mediawiki-codesniffer (v50.0.0)
  - Locking mediawiki/mediawiki-phan-config (0.20.0)
  - Locking mediawiki/minus-x (2.0.1)
  - Locking mediawiki/phan-taint-check-plugin (9.1.0)
  - Locking monolog/monolog (2.11.0)
  - Locking netresearch/jsonmapper (v5.0.1)
  - Locking paragonie/constant_time_encoding (v3.1.3)
  - Locking paragonie/random_compat (v9.99.100)
  - Locking phan/phan (6.0.2)
  - Locking phan/tolerant-php-parser (v0.2.0)
  - Locking phan/var_representation_polyfill (0.1.4)
  - Locking php-parallel-lint/php-console-color (v1.0.1)
  - Locking php-parallel-lint/php-console-highlighter (v1.0.0)
  - Locking php-parallel-lint/php-parallel-lint (v1.4.0)
  - Locking phpcsstandards/phpcsextra (1.4.0)
  - Locking phpcsstandards/phpcsutils (1.2.2)
  - Locking phpdocumentor/reflection-common (2.2.0)
  - Locking phpdocumentor/reflection-docblock (6.0.3)
  - Locking phpdocumentor/type-resolver (2.0.0)
  - Locking phpmailer/phpmailer (v6.12.0)
  - Locking phpseclib/phpseclib (3.0.52)
  - Locking phpstan/phpdoc-parser (2.3.2)
  - Locking predis/predis (v1.1.10)
  - Locking psr/cache (1.0.1)
  - Locking psr/clock (1.0.0)
  - Locking psr/container (2.0.2)
  - Locking psr/http-client (1.0.3)
  - Locking psr/http-factory (1.1.0)
  - Locking psr/http-message (2.0)
  - Locking psr/log (1.1.4)
  - Locking ralouphie/getallheaders (3.0.3)
  - Locking relisten/forceutf8 (1.1.0)
  - Locking respect/stringifier (1.0.0)
  - Locking respect/validation (2.4.12)
  - Locking sabre/event (6.1.0)
  - Locking squizlabs/php_codesniffer (3.13.5)
  - Locking symfony/console (v7.4.9)
  - Locking symfony/deprecation-contracts (v3.6.0)
  - Locking symfony/http-foundation (v6.4.35)
  - Locking symfony/polyfill-ctype (v1.37.0)
  - Locking symfony/polyfill-intl-grapheme (v1.37.0)
  - Locking symfony/polyfill-intl-normalizer (v1.37.0)
  - Locking symfony/polyfill-mbstring (v1.37.0)
  - Locking symfony/polyfill-php83 (v1.37.0)
  - Locking symfony/service-contracts (v3.6.1)
  - Locking symfony/string (v7.4.8)
  - Locking symfony/yaml (v7.4.8)
  - Locking webmozart/assert (2.3.0)
  - Locking whichbrowser/parser (v2.1.8)
  - Locking wikimedia/remex-html (5.1.0)
  - Locking wikimedia/smash-pig (v1.2.4.4)
  - Locking wikimedia/testing-access-wrapper (4.0.0)
  - Locking wikimedia/utfnormal (4.0.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 78 installs, 0 updates, 0 removals
  - Downloading psr/cache (1.0.1)
  - Downloading addshore/psr-6-mediawiki-bagostuff-adapter (0.1)
  - Downloading clio/clio (0.1.8)
  - Downloading lcobucci/clock (3.3.1)
  - Downloading lcobucci/jwt (4.3.0)
  - Downloading maxmind/web-service-common (v0.9.0)
  - Downloading geoip2/geoip2 (v2.13.0)
  - Downloading maxmind/minfraud (v1.23.0)
  - Downloading relisten/forceutf8 (1.1.0)
  - Downloading symfony/polyfill-php83 (v1.37.0)
  - Downloading whichbrowser/parser (v2.1.8)
  - Downloading symfony/http-foundation (v6.4.35)
  - Downloading predis/predis (v1.1.10)
  - Downloading gr4vy/gr4vy-php (v0.27.0)
  - Downloading corneltek/getoptionkit (2.7.3)
  - Downloading coderkungfu/php-queue (1.0.2)
  - Downloading brick/money (0.10.3)
  - Syncing amzn/login-and-pay-with-amazon-sdk-php (2.5.0) into cache
  - Downloading wikimedia/smash-pig (v1.2.4.4)
  0/18 [>---------------------------]   0%
  7/18 [==========>-----------------]  38%
 15/18 [=======================>----]  83%
 17/18 [==========================>-]  94%
 18/18 [============================] 100%
  - Installing squizlabs/php_codesniffer (3.13.5): Extracting archive
  - Installing dealerdirect/phpcodesniffer-composer-installer (v1.2.0): Extracting archive
  - Installing psr/cache (1.0.1): Extracting archive
  - Installing addshore/psr-6-mediawiki-bagostuff-adapter (0.1): Extracting archive
  - Installing brick/math (0.14.8): Extracting archive
  - Installing clio/clio (0.1.8): Extracting archive
  - Installing composer/pcre (3.3.2): Extracting archive
  - Installing symfony/deprecation-contracts (v3.6.0): Extracting archive
  - Installing psr/http-message (2.0): Extracting archive
  - Installing psr/http-client (1.0.3): Extracting archive
  - Installing ralouphie/getallheaders (3.0.3): Extracting archive
  - Installing psr/http-factory (1.1.0): Extracting archive
  - Installing guzzlehttp/psr7 (2.9.0): Extracting archive
  - Installing guzzlehttp/promises (2.3.0): Extracting archive
  - Installing guzzlehttp/guzzle (7.10.0): Extracting archive
  - Installing psr/clock (1.0.0): Extracting archive
  - Installing lcobucci/clock (3.3.1): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.37.0): Extracting archive
  - Installing lcobucci/jwt (4.3.0): Extracting archive
  - Installing maxmind-db/reader (v1.13.1): Extracting archive
  - Installing respect/stringifier (1.0.0): Extracting archive
  - Installing respect/validation (2.4.12): Extracting archive
  - Installing composer/ca-bundle (1.5.11): Extracting archive
  - Installing maxmind/web-service-common (v0.9.0): Extracting archive
  - Installing geoip2/geoip2 (v2.13.0): Extracting archive
  - Installing maxmind/minfraud (v1.23.0): Extracting archive
  - Installing phpcsstandards/phpcsutils (1.2.2): Extracting archive
  - Installing phpcsstandards/phpcsextra (1.4.0): Extracting archive
  - Installing composer/spdx-licenses (1.5.10): Extracting archive
  - Installing composer/semver (3.4.4): Extracting archive
  - Installing mediawiki/mediawiki-codesniffer (v50.0.0): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.37.0): Extracting archive
  - Installing symfony/polyfill-intl-grapheme (v1.37.0): Extracting archive
  - Installing symfony/polyfill-ctype (v1.37.0): Extracting archive
  - Installing symfony/string (v7.4.8): Extracting archive
  - Installing psr/container (2.0.2): Extracting archive
  - Installing symfony/service-contracts (v3.6.1): Extracting archive
  - Installing symfony/console (v7.4.9): Extracting archive
  - Installing sabre/event (6.1.0): Extracting archive
  - Installing phan/var_representation_polyfill (0.1.4): Extracting archive
  - Installing phan/tolerant-php-parser (v0.2.0): Extracting archive
  - Installing netresearch/jsonmapper (v5.0.1): Extracting archive
  - Installing webmozart/assert (2.3.0): Extracting archive
  - Installing phpstan/phpdoc-parser (2.3.2): Extracting archive
  - Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
  - Installing doctrine/deprecations (1.1.6): Extracting archive
  - Installing phpdocumentor/type-resolver (2.0.0): Extracting archive
  - Installing phpdocumentor/reflection-docblock (6.0.3): Extracting archive
  - Installing danog/advanced-json-rpc (v3.2.3): Extracting archive
  - Installing psr/log (1.1.4): Extracting archive
  - Installing composer/xdebug-handler (3.0.5): Extracting archive
  - Installing phan/phan (6.0.2): Extracting archive
  - Installing mediawiki/phan-taint-check-plugin (9.1.0): Extracting archive
  - Installing mediawiki/mediawiki-phan-config (0.20.0): Extracting archive
  - Installing mediawiki/minus-x (2.0.1): Extracting archive
  - Installing monolog/monolog (2.11.0): Extracting archive
  - Installing paragonie/constant_time_encoding (v3.1.3): Extracting archive
  - Installing paragonie/random_compat (v9.99.100): Extracting archive
  - Installing php-parallel-lint/php-console-color (v1.0.1): Extracting archive
  - Installing php-parallel-lint/php-console-highlighter (v1.0.0): Extracting archive
  - Installing php-parallel-lint/php-parallel-lint (v1.4.0): Extracting archive
  - Installing relisten/forceutf8 (1.1.0): Extracting archive
  - Installing symfony/polyfill-php83 (v1.37.0): Extracting archive
  - Installing whichbrowser/parser (v2.1.8): Extracting archive
  - Installing wikimedia/utfnormal (4.0.0): Extracting archive
  - Installing wikimedia/remex-html (5.1.0): Extracting archive
  - Installing symfony/yaml (v7.4.8): Extracting archive
  - Installing symfony/http-foundation (v6.4.35): Extracting archive
  - Installing predis/predis (v1.1.10): Extracting archive
  - Installing phpseclib/phpseclib (3.0.52): Extracting archive
  - Installing phpmailer/phpmailer (v6.12.0): Extracting archive
  - Installing gr4vy/gr4vy-php (v0.27.0): Extracting archive
  - Installing corneltek/getoptionkit (2.7.3): Extracting archive
  - Installing coderkungfu/php-queue (1.0.2): Extracting archive
  - Installing brick/money (0.10.3): Extracting archive
  - Installing amzn/login-and-pay-with-amazon-sdk-php (2.5.0): Cloning 0c923fe992 from cache
  - Installing wikimedia/smash-pig (v1.2.4.4): Extracting archive
  - Installing wikimedia/testing-access-wrapper (4.0.0): Extracting archive
  0/75 [>---------------------------]   0%
 19/75 [=======>--------------------]  25%
 39/75 [==============>-------------]  52%
 57/75 [=====================>------]  76%
 67/75 [=========================>--]  89%
 75/75 [============================] 100%
34 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating optimized autoload files
31 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
--- stdout ---
PHP CodeSniffer Config installed_paths set to ../../mediawiki/mediawiki-codesniffer,../../phpcsstandards/phpcsextra,../../phpcsstandards/phpcsutils

--- end ---
Upgrading n:eslint-config-wikimedia from 0.32.3 -> 0.32.4
$ /usr/bin/npm install
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex-icons@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN deprecated osenv@0.1.5: This package is no longer supported.
npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated abab@2.0.6: Use your platform's native atob() and btoa() methods instead
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported
npm WARN deprecated domexception@4.0.0: Use your platform's native DOMException instead
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
npm WARN deprecated core-js@2.6.12: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
--- stdout ---

added 1115 packages, and audited 1116 packages in 16s

160 packages are looking for funding
  run `npm fund` for details

10 vulnerabilities (4 low, 2 high, 4 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ package-lock-lint /src/repo/package-lock.json
--- stdout ---
Checking /src/repo/package-lock.json

--- end ---
$ /usr/bin/npm install grunt-eslint@24.3.0 --save-exact
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex-icons@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
--- stdout ---

up to date, audited 1116 packages in 3s

160 packages are looking for funding
  run `npm fund` for details

10 vulnerabilities (4 low, 2 high, 4 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ package-lock-lint /src/repo/package-lock.json
--- stdout ---
Checking /src/repo/package-lock.json

--- end ---
$ ./node_modules/.bin/eslint modules/js/ext.donationInterface.requestNewChecksumLink.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelConfirmation.vue modules/js/ext.donationInterface.monthlyConvert_003.js modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateForm.vue modules/ext.donationInterface.donorPortal/components/DonationsDisclaimerComponent.vue modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionSuccess.vue tests/jest/views/amount-downgrade.test.js ./extension.json modules/js/ext.donationInterface.applePayHelper.js modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateSuccess.vue gravy_gateway/forms/gravy.js tests/jest/components/header.test.js tests/jest/routes/router.test.js tests/jest/mocks/endowment_donations_list.mock.js ./composer.json tests/jest/views/home.test.js modules/ext.donationInterface.donorPortal/components/RadioButtonInput.vue tests/jest/components/recurring-update-success.test.js modules/iframe.liberator.js modules/validate_input.js modules/js/ext.donationInterface.employerExplain.js modules/ext.donationInterface.donorPortal/views/CancelDonations.vue modules/ext.donationInterface.donorPortal/views/LoginView.vue tests/jest/components/greeting_component.test.js modules/ext.donationInterface.donorPortal/views/UpdateDonations.vue tests/jest/views/manage-donations.test.js modules/ext.donationInterface.donorPortal/components/Header.vue dlocal_gateway/forms/dlocal.js modules/js/ext.donationInterface.errorLog.js modules/ext.donationInterface.donorPortal/components/RelatedContentComponent.vue modules/ext.donationInterface.donorPortal/components/DonationsListTable.vue modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseForm.vue modules/ext.donationInterface.donorPortal/components/DonationsHistory.vue tests/jest/components/recurring-cancel-form.test.js ./package-lock.json tests/jest/views/login.test.js tests/jest/components/app.test.js modules/ext.donationInterface.donorPortal/components/GreetingComponent.vue tests/jest/components/recurring-cancel-confirmation.test.js modules/ext.donationInterface.donorPortal/components/DonorCardComponent.vue modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseSuccess.vue tests/jest/components/recurring-cancel-option-container.test.js tests/jest/views/cancel-donations.test.js adyen_gateway/forms/adyen.js ./package.json modules/ext.donationInterface.donorPortal/components/ErrorComponent.vue tests/jest/components/recurring-cancel-success.test.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelAltOptionContainer.vue tests/jest/mocks/donor_data.mock.js tests/jest/components/popup_link.test.js modules/ext.donationInterface.donorPortal/ApiUtils.js modules/js/ext.donationInterface.monthlyConvert.js modules/ext.donationInterface.donorPortal/views/Home.vue modules/js/ext.donationInterface.monthlyConvertMultiplier.js tests/jest/components/donations_history.test.js tests/jest/mocks/contribution_mock.mock.js modules/js/ext.donationInterface.monthlyConvertButtonFlip.js modules/ext.donationInterface.donorPortal/components/DonorContactDetails.vue modules/js/ext.donationInterface.alwaysRedirect.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelSuccess.vue tests/jest/views/pause-donations.test.js tests/jest/components/recurring_contribution_summary.test.js modules/js/ext.donationInterface.monthlyConvert_010.js modules/ext.donationInterface.donorPortal/views/AnnualConversion.vue tests/jest/views/update-donations.test.js modules/ext.donationInterface.donorPortal/trackingParams.js tests/jest/components/error-component.test.js tests/jest/views/annual-conversion.test.js tests/jest/components/contact_details.test.js tests/jest/components/recurring_contribution.test.js ./jest.config.js modules/js/ext.donationInterface.monthlyConvertAnnual.js modules/ext.donationInterface.donorPortal/views/PauseDonations.vue modules/ext.donationInterface.donorPortal/views/ManageDonations.vue tests/jest/components/onetime_contribution.test.js ./Gruntfile.js modules/ext.donationInterface.donorPortal/components/FeedbackSurveyComponent.vue tests/jest/components/recurring-pause-success.test.js ./jest.setup.js modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue paypal_ec_gateway/forms/js/paypal.js braintree_gateway/forms/braintree.js modules/ext.donationInterface.donorPortal/init.js modules/js/ext.donationInterface.forms.js modules/js/ext.donationInterface.employerAutoComplete.js modules/ext.donationInterface.donorPortal/components/App.vue modules/js/ext.donationInterface.emailPreferences.js modules/ext.donationInterface.donorPortal/normalizeInput.js tests/jest/mocks/contact_details.mock.js amazon_gateway/amazon.js modules/ext.donationInterface.donorPortal/components/EndowmentInformationComponent.vue tests/jest/components/feedback-survey_component.test.js tests/jest/components/recurring-update-form.test.js modules/js/ext.donationInterface.recurUpgrade.js modules/js/ext.donationInterface.monthlyConvert_011.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelForm.vue ingenico_gateway/forms/js/ingenico.js modules/js/ext.donationInterface.monthlyConvert_015.js modules/ext.donationInterface.donorPortal/views/AmountDowngrade.vue modules/js/ext.donationInterface.employerExplainAlt.js tests/jest/components/recurring-pause-form.test.js modules/ext.donationInterface.donorPortal/components/RecurringContributionSummary.vue modules/js/skinOverride.js modules/ext.donationInterface.donorPortal/components/OnetimeContribution.vue modules/ext.donationInterface.donorPortal/components/PopupLink.vue tests/jest/mocks/annual_donations_list.mock.js tests/jest/components/donations_list_table.test.js modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionForm.vue modules/js/ext.donationInterface.jaVariant02.js modules/js/ext.donationInterface.validation.js modules/ext.donationInterface.donorPortal/router.js --fix
--- stdout ---

/src/repo/Gruntfile.js
  37:11  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/adyen_gateway/forms/adyen.js
    1:26  warning  'Promise' is already defined as a built-in global variable           no-redeclare
    5:3   warning  'configFromServer' is never reassigned. Use 'const' instead          prefer-const
    6:3   warning  'payment_method' is never reassigned. Use 'const' instead            prefer-const
    8:3   warning  'country' is never reassigned. Use 'const' instead                   prefer-const
    9:3   warning  'language' is never reassigned. Use 'const' instead                  prefer-const
   17:3   warning  'GOOGLEPAY_COMPONENT_TYPE' is never reassigned. Use 'const' instead  prefer-const
   18:3   warning  'ACH_GET_DONOR_ADDRESS' is never reassigned. Use 'const' instead     prefer-const
   25:1   warning  Missing JSDoc @return type                                           jsdoc/require-returns-type
   66:5   warning  Unexpected var, use let or const instead                             no-var
   82:23  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
   84:11  warning  'bContact' is never reassigned. Use 'const' instead                  prefer-const
   85:8   warning  'sContact' is never reassigned. Use 'const' instead                  prefer-const
  133:5   warning  Unexpected var, use let or const instead                             no-var
  164:23  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  223:34  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  227:14  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  313:2   warning  'submitPromise' is never reassigned. Use 'const' instead             prefer-const
  313:22  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  401:6   warning  ES2015 'Object.assign' method is forbidden                           es-x/no-object-assign
  540:4   warning  ES2015 'Object.assign' method is forbidden                           es-x/no-object-assign
  550:4   warning  'containerName' is never reassigned. Use 'const' instead             prefer-const
  554:3   warning  'component_type' is never reassigned. Use 'const' instead            prefer-const
  573:3   warning  'oldShowErrors' is never reassigned. Use 'const' instead             prefer-const
  595:3   warning  'config' is never reassigned. Use 'const' instead                    prefer-const
  603:3   warning  'checkoutPromise' is never reassigned. Use 'const' instead           prefer-const
  627:4   warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  654:4   warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise

/src/repo/amazon_gateway/amazon.js
    3:6   warning  'clientId' is never reassigned. Use 'const' instead                   prefer-const
    4:3   warning  'sellerId' is never reassigned. Use 'const' instead                   prefer-const
    5:3   warning  'sandbox' is never reassigned. Use 'const' instead                    prefer-const
    6:3   warning  'returnUrl' is never reassigned. Use 'const' instead                  prefer-const
    7:3   warning  'widgetScript' is never reassigned. Use 'const' instead               prefer-const
    8:3   warning  'loginScript' is never reassigned. Use 'const' instead                prefer-const
    9:3   warning  'failPage' is never reassigned. Use 'const' instead                   prefer-const
   10:3   warning  'isRecurring' is never reassigned. Use 'const' instead                prefer-const
   14:3   warning  'validTokenPattern' is never reassigned. Use 'const' instead          prefer-const
   14:23  warning  Use a regular expression literal instead of the 'RegExp' constructor  prefer-regex-literals
   22:3   warning  'CARD_SELECT_DELAY' is never reassigned. Use 'const' instead          prefer-const
   98:2   warning  'accessToken' is never reassigned. Use 'const' instead                prefer-const
   99:2   warning  'loginError' is never reassigned. Use 'const' instead                 prefer-const
  129:12  warning  Avoid direct access to document.cookie. Use mw.cookie instead         mediawiki/no-cookie
  268:8   warning  Selector extensions are not allowed                                   no-jquery/no-sizzle

/src/repo/braintree_gateway/forms/braintree.js
  10:6  warning  'di' is never reassigned. Use 'const' instead              prefer-const
  12:3  warning  'payment_method' is never reassigned. Use 'const' instead  prefer-const
  13:3  warning  'scripts' is never reassigned. Use 'const' instead         prefer-const

/src/repo/dlocal_gateway/forms/dlocal.js
  27:7  warning  'dlocalInstance' is never reassigned. Use 'const' instead   prefer-const
  28:4  warning  'fields' is never reassigned. Use 'const' instead           prefer-const
  33:4  warning  'commonStyle' is never reassigned. Use 'const' instead      prefer-const
  49:3  warning  'cardField' is never reassigned. Use 'const' instead        prefer-const
  55:3  warning  'expirationField' is never reassigned. Use 'const' instead  prefer-const
  61:3  warning  'cvvField' is never reassigned. Use 'const' instead         prefer-const

/src/repo/gravy_gateway/forms/gravy.js
  454:43  warning  'appleSession' is already declared in the upper scope on line 14 column 3  no-shadow

/src/repo/modules/ext.donationInterface.donorPortal/ApiUtils.js
  13:16  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsDisclaimerComponent.vue
  4:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  6:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsHistory.vue
  128:25  warning  'panel' is already declared in the upper scope on line 138 column 10  no-shadow

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsListTable.vue
  21:22  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  41:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionForm.vue
   35:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
   55:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  100:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionSuccess.vue
  13:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  15:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelSuccess.vue
  13:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue
  33:29  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseSuccess.vue
  13:31  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateSuccess.vue
  15:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/views/LoginView.vue
   8:6   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  37:7   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  66:8   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  76:17  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/iframe.liberator.js
  1:10  warning  'self' is already defined as a built-in global variable  no-redeclare

/src/repo/modules/js/ext.donationInterface.applePayHelper.js
  4:1  warning  Missing JSDoc @param "$" type   jsdoc/require-param-type
  5:1  warning  Missing JSDoc @param "mw" type  jsdoc/require-param-type

/src/repo/modules/js/ext.donationInterface.employerAutoComplete.js
  28:21  warning  Prefer .then to .done  no-jquery/no-done-fail

/src/repo/modules/js/ext.donationInterface.errorLog.js
  16:3  warning  'postdata' is never reassigned. Use 'const' instead  prefer-const

/src/repo/modules/js/ext.donationInterface.forms.js
    4:1   warning  Missing JSDoc @param "$" type                        jsdoc/require-param-type
    5:1   warning  Missing JSDoc @param "mw" type                       jsdoc/require-param-type
   74:27  warning  Selector extensions are not allowed                  no-jquery/no-sizzle
   90:12  warning  '$element' is never reassigned. Use 'const' instead  prefer-const
  107:1   warning  Missing JSDoc @param "checkboxName" type             jsdoc/require-param-type
  111:12  warning  '$element' is never reassigned. Use 'const' instead  prefer-const
  126:1   warning  The type 'result' is undefined                       jsdoc/no-undefined-types
  148:3   warning  'sendData' is never reassigned. Use 'const' instead  prefer-const
  187:4   warning  ES2015 'Object.assign' method is forbidden           es-x/no-object-assign
  239:14  warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  269:10  warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  283:4   warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  321:10  warning  Selector extensions are not allowed                  no-jquery/no-sizzle
  325:30  warning  Selector extensions are not allowed                  no-jquery/no-sizzle

/src/repo/modules/js/ext.donationInterface.jaVariant02.js
  8:1  warning  Missing JSDoc @param "mw" type  jsdoc/require-param-type
  9:1  warning  Missing JSDoc @param "$" type   jsdoc/require-param-type

/src/repo/modules/js/ext.donationInterface.monthlyConvert.js
    2:6   warning  'mc' is never reassigned. Use 'const' instead                         prefer-const
    6:3   warning  'tyUrl' is never reassigned. Use 'const' instead                      prefer-const
    9:3   warning  'convertAmounts' is never reassigned. Use 'const' instead             prefer-const
   17:3   warning  'numAmounts' is never reassigned. Use 'const' instead                 prefer-const
   37:49  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
   78:39  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
  147:51  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
  148:7   warning  'rates' is never reassigned. Use 'const' instead                      prefer-const
  149:4   warning  'amountRules' is never reassigned. Use 'const' instead                prefer-const
  151:4   warning  '$smallAmountMessage' is never reassigned. Use 'const' instead        prefer-const
  161:3   warning  'formattedMin' is never reassigned. Use 'const' instead               prefer-const
  177:4   warning  'locale' is never reassigned. Use 'const' instead                     prefer-const
  180:3   warning  'presetAmount' is never reassigned. Use 'const' instead               prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvertAnnual.js
   3:7   warning  'mc' is never reassigned. Use 'const' instead                        prefer-const
   3:31  warning  'originalGetSendData' is never reassigned. Use 'const' instead       prefer-const
   4:4   warning  'originalAmount' is never reassigned. Use 'const' instead            prefer-const
   5:4   warning  '$otherAmountMonthlyInput' is never reassigned. Use 'const' instead  prefer-const
   5:62  warning  '$otherAmountAnnualInput' is never reassigned. Use 'const' instead   prefer-const
   6:4   warning  '$otherMonthlySubmit' is never reassigned. Use 'const' instead       prefer-const
   6:60  warning  '$otherAnnualSubmit' is never reassigned. Use 'const' instead        prefer-const
   7:4   warning  '$smallAmountMessage' is never reassigned. Use 'const' instead       prefer-const
  15:3   warning  'originalAmountFormatted' is never reassigned. Use 'const' instead   prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvertMultiplier.js
  3:7  warning  'mc' is never reassigned. Use 'const' instead              prefer-const
  4:3  warning  'originalAmount' is never reassigned. Use 'const' instead  prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvert_011.js
  3:7  warning  'mc' is never reassigned. Use 'const' instead              prefer-const
  4:4  warning  'locale' is never reassigned. Use 'const' instead          prefer-const
  5:3  warning  'originalAmount' is never reassigned. Use 'const' instead  prefer-const
  6:3  warning  'currency' is never reassigned. Use 'const' instead        prefer-const
  7:3  warning  'presetAmount' is never reassigned. Use 'const' instead    prefer-const
  8:3  warning  'formattedAsk' is never reassigned. Use 'const' instead    prefer-const

/src/repo/modules/js/ext.donationInterface.recurUpgrade.js
   3:7  warning  '$submitButton' is never reassigned. Use 'const' instead      prefer-const
   4:4  warning  '$amountField' is never reassigned. Use 'const' instead       prefer-const
   5:4  warning  '$otherAmountField' is never reassigned. Use 'const' instead  prefer-const
   6:4  warning  '$totalMessage' is never reassigned. Use 'const' instead      prefer-const
   7:4  warning  '$newTotalAmount' is never reassigned. Use 'const' instead    prefer-const
   8:4  warning  '$form' is never reassigned. Use 'const' instead              prefer-const
   9:4  warning  'originalAmount' is never reassigned. Use 'const' instead     prefer-const
  10:4  warning  'currency' is never reassigned. Use 'const' instead           prefer-const
  11:4  warning  'maximum' is never reassigned. Use 'const' instead            prefer-const
  12:4  warning  'nextDateFormatted' is never reassigned. Use 'const' instead  prefer-const
  14:4  warning  'preSelectAmount' is never reassigned. Use 'const' instead    prefer-const
  38:4  warning  'valueIsValid' is never reassigned. Use 'const' instead       prefer-const

/src/repo/modules/js/ext.donationInterface.validation.js
   7:1   warning  Missing JSDoc @param "$" type                                      jsdoc/require-param-type
   8:1   warning  Missing JSDoc @param "mw" type                                     jsdoc/require-param-type
  11:6   warning  'di' is never reassigned. Use 'const' instead                      prefer-const
  13:3   warning  'mcDomains' is never reassigned. Use 'const' instead               prefer-const
  33:3   warning  'multiCountrySubdomains' is never reassigned. Use 'const' instead  prefer-const
  34:3   warning  'countryTlds' is never reassigned. Use 'const' instead             prefer-const
  40:26  warning  'i' is already declared in the upper scope on line 39 column 36    no-shadow

/src/repo/modules/validate_input.js
    1:1   warning  Missing JSDoc @return declaration                                                    jsdoc/require-returns
    9:3   warning  'rates' is never reassigned. Use 'const' instead                                     prefer-const
   10:3   warning  'amountRules' is never reassigned. Use 'const' instead                               prefer-const
   14:3   warning  '$amountMsg' is never reassigned. Use 'const' instead                                prefer-const
   15:3   warning  'threeDecimalCurrencies' is never reassigned. Use 'const' instead                    prefer-const
   86:3   warning  'invalids' is never reassigned. Use 'const' instead                                  prefer-const
   87:3   warning  'rules' is never reassigned. Use 'const' instead                                     prefer-const
  105:27  warning  'value' is already declared in the upper scope on line 82 column 6                   no-shadow
  107:14  warning  All possible message keys should be documented. See https://w.wiki/4r9a for details  mediawiki/msg-doc
  113:23  warning  'i' is already declared in the upper scope on line 85 column 3                       no-shadow
  145:2   warning  'countryField' is never reassigned. Use 'const' instead                              prefer-const
  168:2   warning  'emailAdd' is never reassigned. Use 'const' instead                                  prefer-const
  220:2   warning  'phoneAdd' is never reassigned. Use 'const' instead                                  prefer-const
  241:11  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie
  242:16  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie
  243:12  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie

/src/repo/paypal_ec_gateway/forms/js/paypal.js
  2:6  warning  'di' is never reassigned. Use 'const' instead     prefer-const
  3:3  warning  'rules' is never reassigned. Use 'const' instead  prefer-const

/src/repo/tests/jest/components/recurring_contribution.test.js
  57:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign
  71:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign
  88:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/amount-downgrade.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/annual-conversion.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/cancel-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/home.test.js
  2:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/manage-donations.test.js
  4:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/pause-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/update-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

✖ 170 problems (0 errors, 170 warnings)


--- end ---
$ ./node_modules/.bin/eslint modules/js/ext.donationInterface.requestNewChecksumLink.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelConfirmation.vue modules/js/ext.donationInterface.monthlyConvert_003.js modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateForm.vue modules/ext.donationInterface.donorPortal/components/DonationsDisclaimerComponent.vue modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionSuccess.vue tests/jest/views/amount-downgrade.test.js ./extension.json modules/js/ext.donationInterface.applePayHelper.js modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateSuccess.vue gravy_gateway/forms/gravy.js tests/jest/components/header.test.js tests/jest/routes/router.test.js tests/jest/mocks/endowment_donations_list.mock.js ./composer.json tests/jest/views/home.test.js modules/ext.donationInterface.donorPortal/components/RadioButtonInput.vue tests/jest/components/recurring-update-success.test.js modules/iframe.liberator.js modules/validate_input.js modules/js/ext.donationInterface.employerExplain.js modules/ext.donationInterface.donorPortal/views/CancelDonations.vue modules/ext.donationInterface.donorPortal/views/LoginView.vue tests/jest/components/greeting_component.test.js modules/ext.donationInterface.donorPortal/views/UpdateDonations.vue tests/jest/views/manage-donations.test.js modules/ext.donationInterface.donorPortal/components/Header.vue dlocal_gateway/forms/dlocal.js modules/js/ext.donationInterface.errorLog.js modules/ext.donationInterface.donorPortal/components/RelatedContentComponent.vue modules/ext.donationInterface.donorPortal/components/DonationsListTable.vue modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseForm.vue modules/ext.donationInterface.donorPortal/components/DonationsHistory.vue tests/jest/components/recurring-cancel-form.test.js ./package-lock.json tests/jest/views/login.test.js tests/jest/components/app.test.js modules/ext.donationInterface.donorPortal/components/GreetingComponent.vue tests/jest/components/recurring-cancel-confirmation.test.js modules/ext.donationInterface.donorPortal/components/DonorCardComponent.vue modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseSuccess.vue tests/jest/components/recurring-cancel-option-container.test.js tests/jest/views/cancel-donations.test.js adyen_gateway/forms/adyen.js ./package.json modules/ext.donationInterface.donorPortal/components/ErrorComponent.vue tests/jest/components/recurring-cancel-success.test.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelAltOptionContainer.vue tests/jest/mocks/donor_data.mock.js tests/jest/components/popup_link.test.js modules/ext.donationInterface.donorPortal/ApiUtils.js modules/js/ext.donationInterface.monthlyConvert.js modules/ext.donationInterface.donorPortal/views/Home.vue modules/js/ext.donationInterface.monthlyConvertMultiplier.js tests/jest/components/donations_history.test.js tests/jest/mocks/contribution_mock.mock.js modules/js/ext.donationInterface.monthlyConvertButtonFlip.js modules/ext.donationInterface.donorPortal/components/DonorContactDetails.vue modules/js/ext.donationInterface.alwaysRedirect.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelSuccess.vue tests/jest/views/pause-donations.test.js tests/jest/components/recurring_contribution_summary.test.js modules/js/ext.donationInterface.monthlyConvert_010.js modules/ext.donationInterface.donorPortal/views/AnnualConversion.vue tests/jest/views/update-donations.test.js modules/ext.donationInterface.donorPortal/trackingParams.js tests/jest/components/error-component.test.js tests/jest/views/annual-conversion.test.js tests/jest/components/contact_details.test.js tests/jest/components/recurring_contribution.test.js ./jest.config.js modules/js/ext.donationInterface.monthlyConvertAnnual.js modules/ext.donationInterface.donorPortal/views/PauseDonations.vue modules/ext.donationInterface.donorPortal/views/ManageDonations.vue tests/jest/components/onetime_contribution.test.js ./Gruntfile.js modules/ext.donationInterface.donorPortal/components/FeedbackSurveyComponent.vue tests/jest/components/recurring-pause-success.test.js ./jest.setup.js modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue paypal_ec_gateway/forms/js/paypal.js braintree_gateway/forms/braintree.js modules/ext.donationInterface.donorPortal/init.js modules/js/ext.donationInterface.forms.js modules/js/ext.donationInterface.employerAutoComplete.js modules/ext.donationInterface.donorPortal/components/App.vue modules/js/ext.donationInterface.emailPreferences.js modules/ext.donationInterface.donorPortal/normalizeInput.js tests/jest/mocks/contact_details.mock.js amazon_gateway/amazon.js modules/ext.donationInterface.donorPortal/components/EndowmentInformationComponent.vue tests/jest/components/feedback-survey_component.test.js tests/jest/components/recurring-update-form.test.js modules/js/ext.donationInterface.recurUpgrade.js modules/js/ext.donationInterface.monthlyConvert_011.js modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelForm.vue ingenico_gateway/forms/js/ingenico.js modules/js/ext.donationInterface.monthlyConvert_015.js modules/ext.donationInterface.donorPortal/views/AmountDowngrade.vue modules/js/ext.donationInterface.employerExplainAlt.js tests/jest/components/recurring-pause-form.test.js modules/ext.donationInterface.donorPortal/components/RecurringContributionSummary.vue modules/js/skinOverride.js modules/ext.donationInterface.donorPortal/components/OnetimeContribution.vue modules/ext.donationInterface.donorPortal/components/PopupLink.vue tests/jest/mocks/annual_donations_list.mock.js tests/jest/components/donations_list_table.test.js modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionForm.vue modules/js/ext.donationInterface.jaVariant02.js modules/js/ext.donationInterface.validation.js modules/ext.donationInterface.donorPortal/router.js -f json
--- stdout ---
[{"filePath":"/src/repo/Gruntfile.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":37,"column":11,"nodeType":"MemberExpression","messageId":"forbidden","endLine":37,"endColumn":24}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*!\n * Grunt file\n *\n * @package DonationInterface\n */\n\n/* eslint-env node */\nmodule.exports = function ( grunt ) {\n\tconst conf = grunt.file.readJSON( 'extension.json' );\n\tgrunt.loadNpmTasks( 'grunt-banana-checker' );\n\tgrunt.loadNpmTasks( 'grunt-eslint' );\n\tgrunt.loadNpmTasks( 'grunt-stylelint' );\n\n\tgrunt.initConfig( {\n\t\teslint: {\n\t\t\toptions: {\n\t\t\t\tcache: true,\n\t\t\t\tfix: grunt.option( 'fix' )\n\t\t\t},\n\t\t\tall: [\n\t\t\t\t'{.,modules/**}/*.js{,on}',\n\t\t\t\t'!modules/js/{mailcheck,lg-hash,lightgallery}.js',\n\t\t\t\t'modules/ext.donationInterface.donorPortal/**/*.{vue,js}',\n\t\t\t\t'{adyen,amazon,braintree,dlocal,ingenico,paypal_ec,gravy}_gateway/**/*.js',\n\t\t\t\t'tests/**/*.js'\n\t\t\t]\n\t\t},\n\t\tstylelint: {\n\t\t\toptions: {\n\t\t\t\tcache: true\n\t\t\t},\n\t\t\tall: [\n\t\t\t\t'{modules,gateway_forms}/{**/,}*.{css,less}',\n\t\t\t\t'{amazon,ingenico}_gateway/{**/,}*.{css,less}'\n\t\t\t]\n\t\t},\n\t\tbanana: Object.assign(\n\t\t\t{\n\t\t\t\toptions: {\n\t\t\t\t\trequireLowerCase: false\n\t\t\t\t}\n\t\t\t},\n\t\t\tconf.MessagesDirs\n\t\t)\n\t} );\n\n\tgrunt.registerTask( 'test', [ 'eslint', 'stylelint', 'banana' ] );\n\tgrunt.registerTask( 'default', 'test' );\n};\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/adyen_gateway/forms/adyen.js","messages":[{"ruleId":"no-redeclare","severity":1,"message":"'Promise' is already defined as a built-in global variable.","line":1,"column":26,"nodeType":"Block","messageId":"redeclaredAsBuiltin","endLine":1,"endColumn":33},{"ruleId":"prefer-const","severity":1,"message":"'configFromServer' is never reassigned. Use 'const' instead.","line":5,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":5,"endColumn":19},{"ruleId":"prefer-const","severity":1,"message":"'payment_method' is never reassigned. Use 'const' instead.","line":6,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'country' is never reassigned. Use 'const' instead.","line":8,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":8,"endColumn":10},{"ruleId":"prefer-const","severity":1,"message":"'language' is never reassigned. Use 'const' instead.","line":9,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":9,"endColumn":11},{"ruleId":"prefer-const","severity":1,"message":"'GOOGLEPAY_COMPONENT_TYPE' is never reassigned. Use 'const' instead.","line":17,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":17,"endColumn":27},{"ruleId":"prefer-const","severity":1,"message":"'ACH_GET_DONOR_ADDRESS' is never reassigned. Use 'const' instead.","line":18,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":18,"endColumn":24},{"ruleId":"jsdoc/require-returns-type","severity":1,"message":"Missing JSDoc @return type.","line":25,"column":1,"nodeType":"Block","endLine":25,"endColumn":1},{"ruleId":"no-var","severity":1,"message":"Unexpected var, use let or const instead.","line":66,"column":5,"nodeType":"VariableDeclaration","messageId":"unexpectedVar","endLine":68,"endColumn":42},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":82,"column":23,"nodeType":"Identifier","messageId":"forbidden","endLine":82,"endColumn":30},{"ruleId":"prefer-const","severity":1,"message":"'bContact' is never reassigned. Use 'const' instead.","line":84,"column":11,"nodeType":"Identifier","messageId":"useConst","endLine":84,"endColumn":19},{"ruleId":"prefer-const","severity":1,"message":"'sContact' is never reassigned. Use 'const' instead.","line":85,"column":8,"nodeType":"Identifier","messageId":"useConst","endLine":85,"endColumn":16},{"ruleId":"no-var","severity":1,"message":"Unexpected var, use let or const instead.","line":133,"column":5,"nodeType":"VariableDeclaration","messageId":"unexpectedVar","endLine":139,"endColumn":64},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":164,"column":23,"nodeType":"Identifier","messageId":"forbidden","endLine":164,"endColumn":30},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":223,"column":34,"nodeType":"Identifier","messageId":"forbidden","endLine":223,"endColumn":41},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":227,"column":14,"nodeType":"Identifier","messageId":"forbidden","endLine":227,"endColumn":21},{"ruleId":"prefer-const","severity":1,"message":"'submitPromise' is never reassigned. Use 'const' instead.","line":313,"column":2,"nodeType":"Identifier","messageId":"useConst","endLine":313,"endColumn":15},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":313,"column":22,"nodeType":"Identifier","messageId":"forbidden","endLine":313,"endColumn":29},{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":401,"column":6,"nodeType":"MemberExpression","messageId":"forbidden","endLine":401,"endColumn":19},{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":540,"column":4,"nodeType":"MemberExpression","messageId":"forbidden","endLine":540,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'containerName' is never reassigned. Use 'const' instead.","line":550,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":550,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'component_type' is never reassigned. Use 'const' instead.","line":554,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":554,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'oldShowErrors' is never reassigned. Use 'const' instead.","line":573,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":573,"endColumn":16},{"ruleId":"prefer-const","severity":1,"message":"'config' is never reassigned. Use 'const' instead.","line":595,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":595,"endColumn":9},{"ruleId":"prefer-const","severity":1,"message":"'checkoutPromise' is never reassigned. Use 'const' instead.","line":603,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":603,"endColumn":18},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":627,"column":4,"nodeType":"Identifier","messageId":"forbidden","endLine":627,"endColumn":11},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":654,"column":4,"nodeType":"Identifier","messageId":"forbidden","endLine":654,"endColumn":11}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":27,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global AdyenCheckout, Promise */\n( function ( $, mw ) {\n\t// promise objects are for Apple Pay - see comments below\n\tlet checkout, onSubmit, authPromise, submitPromise,\n\t\tconfigFromServer = mw.config.get( 'adyenConfiguration' ),\n\t\tpayment_method = $( '#payment_method' ).val(),\n\t\tonBrandSubmethod = '',\n\t\tcountry = $( '#country' ).val(),\n\t\tlanguage = $( '#language' ).val(),\n\t\t// This is the old-style Google Pay integration type currently active on\n\t\t// our account. Older versions of the Adyen JS SDK treated the 'googlepay'\n\t\t// component type as the old GPay integration, but for newer versions of\n\t\t// the GPay SDK we need to explicitly specify 'paywithgoogle' to get tokens\n\t\t// that work with the old-style integration. At some point we should upgrade\n\t\t// to the new interaction, but that will require coordinating an update to\n\t\t// this constant with an update to our account.\n\t\tGOOGLEPAY_COMPONENT_TYPE = 'paywithgoogle',\n\t\tACH_GET_DONOR_ADDRESS = true; // set false to remove address from form\n\n\t/**\n\t * Get extra configuration values for specific payment types\n\t *\n\t * @param {string} type Adyen-side name of component type\n\t * @param {Object} checkoutConfig The config object used to instantiate the Adyen Checkout object\n\t * @return Object\n\t */\n\tfunction getComponentConfig( type, checkoutConfig ) {\n\t\tconst config = {};\n\t\tswitch ( type ) {\n\t\t\tcase 'card':\n\t\t\t\t// Note: Debug messages are only sent and logged server-side if\n\t\t\t\t// $wgDonationInterfaceLogDebug (or $wgAdyenCheckoutGatewayLogDebug) is true\n\n\t\t\t\tconfig.onBrand = function ( brandInfo ) {\n\t\t\t\t\tconst message = brandInfo.brand ?\n\t\t\t\t\t\t'onBrand returned brand: ' + brandInfo.brand :\n\t\t\t\t\t\t'onBrand returned: ' + JSON.stringify( brandInfo );\n\t\t\t\t\tif ( brandInfo.brand ) {\n\t\t\t\t\t\tonBrandSubmethod = brandInfo.brand;\n\t\t\t\t\t}\n\t\t\t\t\tmw.donationInterface.forms.addDebugMessage( message );\n\t\t\t\t};\n\n\t\t\t\tconfig.onBinLookup = function ( binLookupInfo ) {\n\t\t\t\t\tconst message = binLookupInfo.detectedBrands && binLookupInfo.detectedBrands.length > 0 ?\n\t\t\t\t\t\t'onBinLookup returned detected brands: ' + JSON.stringify( binLookupInfo.detectedBrands ) :\n\t\t\t\t\t\t'onBinLookup returned: ' + JSON.stringify( binLookupInfo );\n\t\t\t\t\tmw.donationInterface.forms.addDebugMessage( message );\n\t\t\t\t};\n\n\t\t\t\tconfig.showBrandsUnderCardNumber = false;\n\t\t\t\treturn config;\n\n\t\t\tcase 'ach':\n\t\t\t\tconfig.billingAddressRequired = ACH_GET_DONOR_ADDRESS;\n\t\t\t\treturn config;\n\t\t\tcase 'ideal':\n\t\t\tcase 'onlineBanking_CZ':\n\t\t\tcase 'sepadirectdebit':\n\t\t\tcase 'vipps':\n\t\t\t\t// for ach, ideal, CZ bank transfers, vipps, and sepa additional config is optional\n\t\t\t\treturn config;\n\n\t\t\tcase 'applepay':\n\t\t\t\t// for applepay, additional config is required\n\t\t\t\tvar amount = {},\n\t\t\t\t\tcurrency = $( '#currency' ).val(),\n\t\t\t\t\tamount_value = $( '#amount' ).val();\n\t\t\t\tamount.currency = currency;\n\t\t\t\tamount.value = amountInMinorUnits( amount_value, currency );\n\t\t\t\tconfig.amount = amount;\n\t\t\t\tconfig.countryCode = country;\n\t\t\t\tconfig.requiredBillingContactFields = [\n\t\t\t\t\t'name',\n\t\t\t\t\t'postalAddress'\n\t\t\t\t];\n\t\t\t\tconfig.requiredShippingContactFields = [\n\t\t\t\t\t'name',\n\t\t\t\t\t'email'\n\t\t\t\t];\n\n\t\t\t\tauthPromise = new Promise( ( authResolve, authReject ) => {\n\t\t\t\t\tconfig.onAuthorized = function ( resolve, reject, event ) {\n\t\t\t\t\t\tlet bContact = event.payment.billingContact,\n\t\t\t\t\t\t\tsContact = event.payment.shippingContact,\n\t\t\t\t\t\t\textraData = {};\n\t\t\t\t\t\textraData = mw.donationInterface.forms.apple.getBestApplePayContactName( extraData, bContact, sContact );\n\t\t\t\t\t\textraData.postal_code = bContact.postalCode;\n\t\t\t\t\t\textraData.state_province = bContact.administrativeArea;\n\t\t\t\t\t\textraData.city = bContact.locality;\n\t\t\t\t\t\tif ( bContact.addressLines.length > 0 ) {\n\t\t\t\t\t\t\textraData.street_address = bContact.addressLines[ 0 ];\n\t\t\t\t\t\t}\n\t\t\t\t\t\textraData.email = sContact.emailAddress;\n\t\t\t\t\t\textraData.payment_submethod = mapAppleNetworkToSubmethod( event.payment.token.paymentMethod.network );\n\t\t\t\t\t\t// We will combine this contact data with a token from the\n\t\t\t\t\t\t// onSubmit event after both events have fired.\n\t\t\t\t\t\tauthResolve( extraData );\n\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t};\n\t\t\t\t} );\n\t\t\t\t// For Apple Pay show the branded button with 'Donate with 🍎Pay'\n\t\t\t\t// text as opposed to our standard blue Donate button\n\t\t\t\tconfig.showPayButton = true;\n\t\t\t\tconfig.buttonType = 'donate';\n\t\t\t\t// When the donor clicks the donate button, this event is fired with\n\t\t\t\t// a validationUrl provided by Apple. We have to make a server-side\n\t\t\t\t// request to get a big blob of Apple Pay session data, then send it\n\t\t\t\t// via the resolve function back to the component, which apparently\n\t\t\t\t// sends it back to the native widget via completeMerchantValidation.\n\t\t\t\t// https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api/providing_merchant_validation\n\t\t\t\tconfig.onValidateMerchant = function ( resolve, reject, validationUrl ) {\n\t\t\t\t\tconst api = new mw.Api();\n\t\t\t\t\tapi.post( {\n\t\t\t\t\t\taction: 'di_applesession_adyen',\n\t\t\t\t\t\tvalidation_url: validationUrl,\n\t\t\t\t\t\twmf_token: $( '#wmf_token' ).val()\n\t\t\t\t\t} ).then( ( data ) => {\n\t\t\t\t\t\tif ( data.result && data.result.errors ) {\n\t\t\t\t\t\t\tmw.donationInterface.validation.showErrors( data.result.errors );\n\t\t\t\t\t\t\treject();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve( data.session );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t};\n\n\t\t\t\treturn config;\n\n\t\t\tcase GOOGLEPAY_COMPONENT_TYPE:\n\t\t\t\t// for googlepay, additional config is required\n\t\t\t\tvar g_amount = {},\n\t\t\t\t\tg_currency = $( '#currency' ).val(),\n\t\t\t\t\tg_amount_value = $( '#amount' ).val(),\n\t\t\t\t\tlanguagesSupportedByGPayButton = [\n\t\t\t\t\t\t'ar', 'bg', 'ca', 'cs', 'da', 'de', 'en', 'el', 'es', 'et', 'fi', 'fr', 'hr', 'id', 'it', 'ja',\n\t\t\t\t\t\t'ko', 'ms', 'nl', 'no', 'pl', 'pt', 'ru', 'sk', 'sl', 'sr', 'sv', 'th', 'tr', 'uk', 'zh'\n\t\t\t\t\t], baseLanguageCode = checkoutConfig.locale.slice( 0, 2 );\n\t\t\t\tg_amount.currency = g_currency;\n\t\t\t\tg_amount.value = amountInMinorUnits( g_amount_value, g_currency );\n\t\t\t\tconfig.amount = g_amount;\n\t\t\t\tconfig.countryCode = country;\n\t\t\t\tconfig.environment = configFromServer.environment.toUpperCase();\n\t\t\t\tconfig.showPayButton = true;\n\t\t\t\t// When we are showing the form in a language for which Google Pay has no\n\t\t\t\t// translations of their button text, use the plain 'GPay' button rather\n\t\t\t\t// than the 'Donate with GPay' button.\n\t\t\t\tif ( !languagesSupportedByGPayButton.includes( baseLanguageCode ) ) {\n\t\t\t\t\tconfig.buttonType = 'plain';\n\t\t\t\t} else {\n\t\t\t\t\tconfig.buttonType = 'donate';\n\t\t\t\t}\n\t\t\t\tconfig.emailRequired = true;\n\t\t\t\tconfig.billingAddressRequired = true;\n\t\t\t\tconfig.allowedCardNetworks = configFromServer.googleAllowedNetworks;\n\t\t\t\tconfig.billingAddressParameters = {\n\t\t\t\t\tformat: 'FULL'\n\t\t\t\t};\n\t\t\t\t// called gatewayMerchantId but actually our account name with Adyen\n\t\t\t\tconfig.gatewayMerchantId = configFromServer.merchantAccountName;\n\t\t\t\tconfig.merchantId = configFromServer.googleMerchantId;\n\n\t\t\t\tauthPromise = new Promise( ( authResolve ) => {\n\t\t\t\t\tconfig.onAuthorized = function ( response ) {\n\t\t\t\t\t\tconst bContact = response.paymentMethodData.info.billingAddress,\n\t\t\t\t\t\t\textraData = {};\n\t\t\t\t\t\textraData.postal_code = bContact.postalCode;\n\t\t\t\t\t\textraData.state_province = bContact.administrativeArea;\n\t\t\t\t\t\textraData.city = bContact.locality;\n\t\t\t\t\t\textraData.street_address = bContact.address1;\n\t\t\t\t\t\textraData.email = response.email;\n\t\t\t\t\t\textraData.full_name = bContact.name;\n\t\t\t\t\t\textraData.payment_submethod = mapAdyenSubmethod(\n\t\t\t\t\t\t\tresponse.paymentMethodData.info.cardNetwork.toLowerCase()\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// We will combine this contact data with a token from the\n\t\t\t\t\t\t// onSubmit event after both events have fired.\n\t\t\t\t\t\tauthResolve( extraData );\n\t\t\t\t\t};\n\t\t\t\t} );\n\t\t\t\treturn config;\n\t\t\tdefault:\n\t\t\t\tthrow new Error( 'Component type not found' );\n\t\t}\n\t}\n\n\t/**\n\t * Given an amount in major currency units, e.g. dollars, returns the\n\t * amount in minor units for the currency, e.g. cents. For non-fractional\n\t * currencies just rounds the amount to the nearest whole number.\n\t *\n\t * @param {number} amount\n\t * @param {string} currency\n\t * @return {number} amount in minor units for specified currency\n\t */\n\tfunction amountInMinorUnits( amount, currency ) {\n\t\tconst threeDecimals = mw.config.get( 'DonationInterfaceThreeDecimalCurrencies' ),\n\t\t\tnoDecimals = mw.config.get( 'DonationInterfaceNoDecimalCurrencies' );\n\n\t\tif ( noDecimals.includes( currency ) ) {\n\t\t\treturn Math.round( amount );\n\t\t}\n\t\tif ( threeDecimals.includes( currency ) ) {\n\t\t\treturn Math.round( amount * 1000 );\n\t\t}\n\t\treturn Math.round( amount * 100 );\n\t}\n\n\t/**\n\t * Set up Adyen Checkout object\n\t *\n\t * @param {Object} config requires clientKey, environment, locale,\n\t *  and paymentMethodsResponse\n\t * @return {AdyenCheckout}\n\t */\n\tfunction getCheckout( config ) {\n\t\tconfig.onSubmit = onSubmit;\n\t\tconfig.onAdditionalDetails = onAdditionalDetails;\n\t\tconfig.onError = onError;\n\t\tconfig.showPayButton = false;\n\t\tconst checkoutObject = new AdyenCheckout( config );\n\t\tif ( checkoutObject instanceof Promise ) {\n\t\t\treturn checkoutObject;\n\t\t}\n\n\t\treturn new Promise( ( resolve, reject ) => {\n\t\t\tresolve( checkoutObject );\n\t\t} );\n\t}\n\n\tfunction mapAppleNetworkToSubmethod( network ) {\n\t\tnetwork = network.toLowerCase();\n\t\tswitch ( network ) {\n\t\t\tcase 'amex':\n\t\t\tcase 'discover':\n\t\t\tcase 'jcb':\n\t\t\tcase 'visa':\n\t\t\t\treturn network;\n\t\t\tcase 'cartesbancaires':\n\t\t\t\treturn 'cb';\n\t\t\tcase 'electron':\n\t\t\t\treturn 'visa-electron';\n\t\t\tcase 'mastercard':\n\t\t\t\treturn 'mc';\n\t\t\tdefault:\n\t\t\t\treturn '';\n\t\t}\n\t}\n\n\t/**\n\t * Get the name of the Adyen Checkout component to instantiate\n\t *\n\t * @param {string} paymentMethod our top-level payment method code\n\t * @return {string} name of Adyen Checkout component to instantiate\n\t */\n\tfunction mapPaymentMethodToComponentType( paymentMethod ) {\n\t\tswitch ( paymentMethod ) {\n\t\t\tcase 'dd':\n\t\t\t\treturn 'ach';\n\t\t\tcase 'cc':\n\t\t\t\treturn 'card';\n\t\t\tcase 'rtbt':\n\t\t\t\tif ( mw.config.get( 'payment_submethod' ) === 'sepadirectdebit' ) {\n\t\t\t\t\treturn 'sepadirectdebit';\n\t\t\t\t} else {\n\t\t\t\t\treturn 'ideal';\n\t\t\t\t}\n\t\t\tcase 'bt':\n\t\t\t\treturn 'onlineBanking_CZ';\n\t\t\tcase 'apple':\n\t\t\t\treturn 'applepay';\n\t\t\tcase 'google':\n\t\t\t\treturn GOOGLEPAY_COMPONENT_TYPE;\n\t\t\tcase 'ew':\n\t\t\t\treturn 'vipps';\n\t\t\tdefault:\n\t\t\t\tthrow new Error( 'paymentMethod not found' );\n\t\t}\n\t}\n\n\t/**\n\t * TODO: should we do this mapping server-side\n\t * using SmashPig's ReferenceData?\n\t *\n\t * @param {string} adyenBrandCode Adyen-side identifier for the payment submethod\n\t * @return {string} Our identifier for the payment submethod\n\t */\n\tfunction mapAdyenSubmethod( adyenBrandCode ) {\n\t\tswitch ( adyenBrandCode ) {\n\t\t\tcase 'bijcard':\n\t\t\t\treturn 'bij';\n\t\t\tcase 'cartebancaire':\n\t\t\t\treturn 'cb';\n\t\t\tcase 'mc-debit':\n\t\t\t\treturn 'mc';\n\t\t\tcase 'visadankort':\n\t\t\t\treturn 'visa';\n\t\t\tcase 'visadebit':\n\t\t\tcase 'vpay':\n\t\t\t\treturn 'visa-debit';\n\t\t\tcase 'visabeneficial':\n\t\t\t\treturn 'visa-beneficial';\n\t\t\tcase 'visaelectron':\n\t\t\t\treturn 'visa-electron';\n\t\t\tcase 'mastercard':\n\t\t\t\treturn 'mc';\n\t\t\tdefault:\n\t\t\t\treturn adyenBrandCode;\n\t\t}\n\t}\n\n\tsubmitPromise = new Promise( ( submitResolve, submitReject ) => {\n\t\tonSubmit = function ( state, component ) {\n\t\t\tlet extraData = {};\n\t\t\t// Submit to our server, unless it's Apple Pay, which submits in\n\t\t\t// the onAuthorized handler.\n\t\t\tif ( mw.donationInterface.validation.validate() && state.isValid ) {\n\t\t\t\tswitch ( payment_method ) {\n\t\t\t\t\tcase 'dd':\n\t\t\t\t\t\textraData = {\n\t\t\t\t\t\t\tencrypted_bank_account_number: state.data.paymentMethod.encryptedBankAccountNumber,\n\t\t\t\t\t\t\tencrypted_bank_location_id: state.data.paymentMethod.encryptedBankLocationId,\n\t\t\t\t\t\t\tfull_name: state.data.paymentMethod.ownerName,\n\t\t\t\t\t\t\tbank_account_type: $( '#bank_account_type' ).val()\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif ( ACH_GET_DONOR_ADDRESS ) {\n\t\t\t\t\t\t\textraData.supplemental_address_1 = state.data.billingAddress.houseNumberOrName !== 'N/A' ? state.data.billingAddress.houseNumberOrName : '';\n\t\t\t\t\t\t\textraData.country = state.data.billingAddress.country;\n\t\t\t\t\t\t\textraData.street_address = state.data.billingAddress.street;\n\t\t\t\t\t\t\textraData.postal_code = state.data.billingAddress.postalCode;\n\t\t\t\t\t\t\textraData.city = state.data.billingAddress.city;\n\t\t\t\t\t\t\textraData.state_province = state.data.billingAddress.stateOrProvince;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'rtbt':\n\t\t\t\t\t\tswitch ( state.data.paymentMethod.type ) {\n\t\t\t\t\t\t\tcase 'ideal':\n\t\t\t\t\t\t\t\textraData = {\n\t\t\t\t\t\t\t\t\t// issuer is bank chosen from dropdown\n\t\t\t\t\t\t\t\t\tissuer_id: state.data.paymentMethod.issuer,\n\t\t\t\t\t\t\t\t\tpayment_submethod: 'rtbt_ideal'\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 'sepadirectdebit':\n\t\t\t\t\t\t\t\textraData = {\n\t\t\t\t\t\t\t\t\tfull_name: state.data.paymentMethod.ownerName,\n\t\t\t\t\t\t\t\t\t// The International Bank Account Number\n\t\t\t\t\t\t\t\t\tiban: state.data.paymentMethod.iban,\n\t\t\t\t\t\t\t\t\tpayment_submethod: 'sepadirectdebit'\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'bt':\n\t\t\t\t\t\textraData = {\n\t\t\t\t\t\t\t// issuer is bank chosen from dropdown\n\t\t\t\t\t\t\tissuer_id: state.data.paymentMethod.issuer\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'cc':\n\t\t\t\t\t\textraData = {\n\t\t\t\t\t\t\tencrypted_card_number: state.data.paymentMethod.encryptedCardNumber,\n\t\t\t\t\t\t\tencrypted_expiry_month: state.data.paymentMethod.encryptedExpiryMonth,\n\t\t\t\t\t\t\tencrypted_expiry_year: state.data.paymentMethod.encryptedExpiryYear,\n\t\t\t\t\t\t\tencrypted_security_code: state.data.paymentMethod.encryptedSecurityCode,\n\t\t\t\t\t\t\t// The code should be available in state.data.paymentMethod.brand, but\n\t\t\t\t\t\t\t// sometimes it's not there. We can usually still find it via component.\n\t\t\t\t\t\t\tpayment_submethod: mapAdyenSubmethod(\n\t\t\t\t\t\t\t\tstate.data.paymentMethod.brand || component.state.brand || onBrandSubmethod\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif ( state.data.browserInfo ) {\n\t\t\t\t\t\t\textraData.color_depth = state.data.browserInfo.colorDepth;\n\t\t\t\t\t\t\textraData.java_enabled = state.data.browserInfo.javaEnabled;\n\t\t\t\t\t\t\textraData.screen_height = state.data.browserInfo.screenHeight;\n\t\t\t\t\t\t\textraData.screen_width = state.data.browserInfo.screenWidth;\n\n\t\t\t\t\t\t\t// Ensure timeZoneOffset is always an integer, rounding down if it's a decimal or float.\n\t\t\t\t\t\t\t// See T380741\n\t\t\t\t\t\t\tif ( typeof state.data.browserInfo.timeZoneOffset !== 'undefined' &&\n\t\t\t\t\t\t\t\t!isNaN( Math.floor( state.data.browserInfo.timeZoneOffset ) ) ) {\n\t\t\t\t\t\t\t\textraData.time_zone_offset = Math.floor( state.data.browserInfo.timeZoneOffset );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\textraData.time_zone_offset = state.data.browserInfo.timeZoneOffset;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'google':\n\t\t\t\t\t\tsubmitResolve( state.data.paymentMethod.googlePayToken );\n\t\t\t\t\t\treturn;\n\t\t\t\t\tcase 'apple':\n\t\t\t\t\t\t// Resolve the submit promise with the Apple Pay token and bail out - we\n\t\t\t\t\t\t// also need to wait for the onAuthorized event with contact data.\n\t\t\t\t\t\tsubmitResolve( state.data.paymentMethod.applePayToken );\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Allow other scripts (e.g. variants) to provide more data to submit\n\t\t\t\tif ( typeof mw.donationInterface.getExtraData === 'function' ) {\n\t\t\t\t\tObject.assign( extraData, mw.donationInterface.getExtraData() );\n\t\t\t\t}\n\n\t\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\t\thandleApiResult, extraData, 'di_donate_adyen'\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t} );\n\n\tfunction handleApiResult( result ) {\n\t\tif ( result.isFailed ) {\n\t\t\tlocation.assign( mw.config.get( 'DonationInterfaceFailUrl' ) );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( result.formData && Object.keys( result.formData ).length > 0 ) {\n\t\t\t// FIXME: reconstructing the raw result from the API\n\t\t\t// which has been normalized down to just these two\n\t\t\t// fields. Should we just pass the raw Adyen API result\n\t\t\t// back to the front end? Seems like we would only want\n\t\t\t// a rawResult property on the front-end donation API\n\t\t\t// response when we are damn sure it's sanitized.\n\t\t\tcheckout.createFromAction( {\n\t\t\t\tpaymentMethodType: 'scheme',\n\t\t\t\turl: result.redirect,\n\t\t\t\tdata: result.formData,\n\t\t\t\tmethod: 'POST',\n\t\t\t\ttype: 'redirect'\n\t\t\t} ).mount( '#action-container' );\n\n\t\t// canShowModal() is just a sanity check to see if the required DOM elements\n\t\t// are there.\n\t\t} else if ( mw.monthlyConvert && mw.monthlyConvert.canShowModal() ) {\n\t\t\tmw.monthlyConvert.init();\n\t\t} else if ( result.redirect ) {\n\t\t\tdocument.location.replace( result.redirect );\n\t\t} else {\n\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceThankYouPage' ) );\n\t\t}\n\t}\n\n\tfunction onAdditionalDetails( state, dropin ) {\n\t\t// Handle 3D secure\n\t}\n\n\t// T292571 try catch the adyen error, see if any connection been blocked, e.g. iframe\n\tfunction onError( error ) {\n\t\t// Ignore blank string - that means a previous error was cleared up\n\t\tif ( typeof error.error === 'string' && error.error === '' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( typeof error.error === 'string' && error.error.slice( 0, 8 ) === 'error.va' ) {\n\t\t\t// T349600 Log validation error codes only if sf-cc-num.02 donate_interface-error-msg-card-number-do-not-match-card-brand)\n\t\t\t// with date time and time zone for adyen to investigate their card validation js issue\n\t\t\tif ( error.error === 'error.va.sf-cc-num.02' ) {\n\t\t\t\terror.error = 'Adyen error: ' + error.error + ' on ' + new Date().toString();\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t// handle component error\n\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t} );\n\t\t}\n\t\tthrow error;\n\t}\n\n\tfunction setLocaleAndTranslations( config, localeFromServer ) {\n\t\t// Adyen supports the locales listed below, according to\n\t\t// https://docs.adyen.com/online-payments/classic-integrations/checkout-sdks/web-sdk/customization/localization/\n\t\tconst adyenSupportedLocale = [\n\t\t\t'zh-CN', 'zh-TW', 'hr-HR', 'cs-CZ',\n\t\t\t'da-DK', 'nl-NL', 'en-US', 'fi-FI',\n\t\t\t'fr-FR', 'de-DE', 'el-GR', 'hu-HU',\n\t\t\t'it-IT', 'ja-JP', 'ko-KR', 'no-NO',\n\t\t\t'pl-PL', 'pt-BR', 'ro-RO', 'ru-RU',\n\t\t\t'sk-SK', 'sl-SL', 'es-ES', 'sv-SE'\n\t\t], baseLocaleFromServer = localeFromServer.slice( 0, 2 );\n\n\t\t// We support Norwegian Bokmal (nb) but Adyen's components just support the generic 'no' Norwegian code\n\t\tif ( baseLocaleFromServer === 'nb' ) {\n\t\t\tconfig.locale = 'no-NO';\n\t\t} else {\n\t\t\tconfig.locale = localeFromServer;\n\t\t}\n\n\t\tconfig.translations = {};\n\t\t// Check if donor's language is unsupported by Adyen and we need to provide our own customized translation\n\t\t// Adyen supports ar as Arabic - International and doesn't check the country part\n\t\tif ( baseLocaleFromServer !== 'ar' && !adyenSupportedLocale.includes( config.locale ) ) {\n\t\t\tconfig.translations[ config.locale ] = {\n\t\t\t\t//title\n\t\t\t\t'creditCard.numberField.title': mw.msg( 'donate_interface-credit-card-number' ),\n\t\t\t\t'creditCard.expiryDateField.title': mw.msg( 'donate_interface-credit-card-expiration' ),\n\t\t\t\t'creditCard.cvcField.title': mw.msg( 'donate_interface-cvv' ),\n\t\t\t\t//placeholder\n\t\t\t\t'creditCard.expiryDateField.placeholder': mw.msg( 'donate_interface-expiry-date-field-placeholder' ),\n\t\t\t\t'creditCard.cvcField.placeholder.3digits': mw.msg( 'donate_interface-cvv-placeholder-3-digits' ),\n\t\t\t\t'creditCard.cvcField.placeholder.4digits': mw.msg( 'donate_interface-cvv-placeholder-4-digits' ),\n\t\t\t\t//error\n\t\t\t\t'creditCard.numberField.invalid': mw.msg( 'donate_interface-error-msg-invalid-card-number' ),\n\t\t\t\t'creditCard.expiryDateField.invalid': mw.msg( 'donate_interface-error-msg-expiry-date-field-invalid' ),\n\t\t\t\t'error.va.gen.01': mw.msg( 'donate_interface-error-msg-incomplete-field' ),\n\t\t\t\t'error.va.gen.02': mw.msg( 'donate_interface-error-msg-field-not-valid' ),\n\t\t\t\t'error.va.sf-cc-num.01': mw.msg( 'donate_interface-error-msg-invalid-card-number' ),\n\t\t\t\t'error.va.sf-cc-num.02': mw.msg( 'donate_interface-error-msg-card-number-do-not-match-card-brand' ),\n\t\t\t\t'error.va.sf-cc-num.03': mw.msg( 'donate_interface-error-msg-unsupported-card-entered' ),\n\t\t\t\t'error.va.sf-cc-dat.01': mw.msg( 'donate_interface-error-msg-card-too-old' ),\n\t\t\t\t'error.va.sf-cc-dat.02': mw.msg( 'donate_interface-error-msg-date-too-far-in-the-future' )\n\t\t\t};\n\t\t} else if ( config.locale === 'nl-NL' ) {\n\t\t\tconfig.translations[ config.locale ] = {\n\t\t\t\t'idealIssuer.selectField.placeholder': mw.msg( 'donate_interface-rtbt-issuer_id' )\n\t\t\t};\n\t\t} else if ( language === 'ja' ) {\n\t\t\tconfig.translations[ config.locale ] = {\n\t\t\t\t'creditCard.expiryDateField.placeholder': mw.msg( 'donate_interface-expiry-date-field-placeholder' ),\n\t\t\t\t'creditCard.cvcField.placeholder.3digits': '',\n\t\t\t\t'creditCard.cvcField.placeholder.4digits': ''\n\t\t\t};\n\t\t} else {\n\t\t\tconfig.translations[ config.locale ] = {};\n\t\t}\n\t\tif ( mw.config.get( 'payment_submethod' ) === 'ach' ) {\n\t\t\tconfig.translations[ config.locale ] = {\n\t\t\t\t'error.va.sf-ach-loc.02': mw.msg( 'donate_interface-ach-invalid-routing-number-count' ),\n\t\t\t\t'error.va.sf-ach-num.02': mw.msg( 'donate_interface-ach-invalid-account-number-count' )\n\t\t\t};\n\t\t}\n\n\t\t// if sepa, update holder name to account holder name\n\t\tif ( mw.config.get( 'payment_submethod' ) === 'sepadirectdebit' ) {\n\t\t\tconfig.translations[ config.locale ][ 'sepa.ownerName' ] = mw.msg( 'donate_interface-bt-account_holder' );\n\t\t}\n\t\t// Allow other scripts (e.g. variants) to provide more translations to the Adyen components\n\t\tif ( mw.donationInterface.extraTranslations ) {\n\t\t\tObject.assign( config.translations[ config.locale ], mw.donationInterface.extraTranslations );\n\t\t}\n\t}\n\n\t/**\n\t * Runs as soon as the external Adyen checkout script is loaded\n\t */\n\tfunction setup() {\n\t\tlet component_type,\n\t\t\tconfig,\n\t\t\tcontainerName = 'component-container',\n\t\t\toldShowErrors,\n\t\t\tcheckoutPromise;\n\n\t\tcomponent_type = mapPaymentMethodToComponentType( payment_method );\n\n\t\t// Drop in the adyen components placeholder container\n\t\t$( '.submethods' ).before(\n\t\t\t'<div id=\"' + containerName + '\" />'\n\t\t).before(\n\t\t\t'<div id=\"action-container\" />'\n\t\t);\n\n\t\t// add name placeholder for ja JP\n\t\tif ( language === 'ja' ) {\n\t\t\t$( '#last_name' ).attr( 'placeholder', '鈴木' );\n\t\t\t$( '#first_name' ).attr( 'placeholder', '太郎' );\n\t\t}\n\n\t\t// Override validation's showErrors function to add error\n\t\t// highlights to the outer div around the secure field iframe.\n\t\t// FIXME: cleaner object-oriented JS with inheritance would\n\t\t// make this prettier. See https://phabricator.wikimedia.org/T293287\n\t\toldShowErrors = mw.donationInterface.validation.showErrors;\n\t\tmw.donationInterface.validation.showErrors = function ( errors ) {\n\t\t\tlet adyenFieldName;\n\t\t\t$.each( errors, ( field ) => {\n\t\t\t\tadyenFieldName = false;\n\t\t\t\tif ( field === 'card_num' || field === 'encrypted_card_number' ) {\n\t\t\t\t\tadyenFieldName = 'encryptedCardNumber';\n\t\t\t\t} else if ( field === 'encrypted_expiry_month' || field === 'encrypted_expiry_year' ) {\n\t\t\t\t\tadyenFieldName = 'encryptedExpiryDate';\n\t\t\t\t} else if ( field === 'cvv' ) {\n\t\t\t\t\tadyenFieldName = 'encryptedSecurityCode';\n\t\t\t\t}\n\t\t\t\tif ( adyenFieldName ) {\n\t\t\t\t\t$( 'span[data-cse=' + adyenFieldName + ']' )\n\t\t\t\t\t\t.closest( '.adyen-checkout__input-wrapper' )\n\t\t\t\t\t\t.addClass( 'errorHighlight' );\n\t\t\t\t}\n\t\t\t} );\n\t\t\toldShowErrors( errors );\n\t\t};\n\n\t\t// Copy values to leave the mw.config setting untouched\n\t\tconfig = {\n\t\t\tclientKey: configFromServer.clientKey,\n\t\t\tenvironment: configFromServer.environment,\n\t\t\tpaymentMethodsResponse: configFromServer.paymentMethodsResponse\n\t\t};\n\n\t\tsetLocaleAndTranslations( config, configFromServer.locale );\n\n\t\tcheckoutPromise = getCheckout( config );\n\t\tcheckoutPromise.then( ( checkoutObject ) => {\n\t\t\tcheckout = checkoutObject;\n\t\t\tcreateAndMountComponent( config, component_type, containerName );\n\t\t} );\n\t}\n\n\tfunction createAndMountComponent( config, component_type, containerName ) {\n\t\tconst component_config = getComponentConfig( component_type, config ),\n\t\t\tcomponent = checkout.create( component_type, component_config );\n\n\t\tif ( component_type === GOOGLEPAY_COMPONENT_TYPE ) {\n\t\t\tcomponent.isAvailable().then( () => {\n\t\t\t\tcomponent.mount( '#' + containerName );\n\t\t\t} ).catch( () => {\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.message(\n\t\t\t\t\t\t'donate_interface-error-msg-google_pay_unsupported',\n\t\t\t\t\t\tmw.config.get( 'DonationInterfaceOtherWaysURL' )\n\t\t\t\t\t).plain()\n\t\t\t\t} );\n\t\t\t} );\n\t\t\t// For Google Pay, we need contact data from the onAuthorized event and token\n\t\t\t// data from the onSubmit event before we can make our MediaWiki API call.\n\t\t\tPromise.all( [ submitPromise, authPromise ] ).then( ( values ) => {\n\t\t\t\tconst extraData = values[ 1 ];\n\t\t\t\textraData.payment_token = values[ 0 ];\n\t\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\t\thandleApiResult, extraData, 'di_donate_adyen'\n\t\t\t\t);\n\t\t\t} ).catch( ( err ) => {\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t} );\n\t\t\t\t// Let error bubble up to window.onerror handler so the errorLog\n\t\t\t\t// module sends it to our client-side logging endpoint.\n\t\t\t\tthrow err;\n\t\t\t} );\n\t\t} else if ( component_type === 'applepay' ) {\n\t\t\tcomponent.isAvailable().then( () => {\n\t\t\t\tcomponent.mount( '#' + containerName );\n\t\t\t} ).catch( () => {\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.message(\n\t\t\t\t\t\t'donate_interface-error-msg-apple_pay_unsupported',\n\t\t\t\t\t\tmw.config.get( 'DonationInterfaceOtherWaysURL' )\n\t\t\t\t\t).plain()\n\t\t\t\t} );\n\t\t\t} );\n\t\t\t// For Apple Pay, we need contact data from the onAuthorized event and token\n\t\t\t// data from the onSubmit event before we can make our MediaWiki API call.\n\t\t\tPromise.all( [ submitPromise, authPromise ] ).then( ( values ) => {\n\t\t\t\tconst extraData = values[ 1 ];\n\t\t\t\textraData.payment_token = values[ 0 ];\n\t\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\t\thandleApiResult, extraData, 'di_donate_adyen'\n\t\t\t\t);\n\t\t\t} ).catch( ( err ) => {\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t} );\n\t\t\t\t// Let error bubble up to window.onerror handler so the errorLog\n\t\t\t\t// module sends it to our client-side logging endpoint.\n\t\t\t\tthrow err;\n\t\t\t} );\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tcomponent.mount( '#' + containerName );\n\t\t\t} catch ( err ) {\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t} );\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\t// For everything except Apple and google\n\t\t\t// Pay, show our standard 'Donate' button\n\t\t\t$( '#paymentSubmit' ).show();\n\t\t\t$( '#paymentSubmitBtn' ).click( mw.util.debounce( ( evt ) => {\n\t\t\t\tcomponent.submit( evt );\n\t\t\t}, 100 ) );\n\t\t}\n\t}\n\n\t$( () => {\n\t\tif ( !configFromServer ) {\n\t\t\t// If the configuration has not been passed from the server, we are likely on the\n\t\t\t// ResultSwitcher page and have just been loaded incidentally to make a form for\n\t\t\t// a backdrop of the monthly convert popup. As the rest of this function is only\n\t\t\t// needed to set up payment widgets which will not be needed here, just quit.\n\t\t\t// It might be better to stop loading adyen.js in that situation, but that's a\n\t\t\t// bigger refactor than we want to do right now.\n\t\t\treturn;\n\t\t}\n\t\tif ( payment_method === 'google' ) {\n\t\t\t// loadScript will display an error message when the script fails to load\n\t\t\t// so we just suppress the rejection with an empty catch block here.\n\t\t\tmw.donationInterface.forms.loadScript( configFromServer.googleScript )\n\t\t\t\t.catch( () => {} );\n\t\t}\n\t\tmw.donationInterface.forms.loadScript( configFromServer.script.src, true, configFromServer.script.integrity )\n\t\t\t.then( setup )\n\t\t\t.catch( () => {} );\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/amazon_gateway/amazon.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'clientId' is never reassigned. Use 'const' instead.","line":3,"column":6,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":14},{"ruleId":"prefer-const","severity":1,"message":"'sellerId' is never reassigned. Use 'const' instead.","line":4,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":4,"endColumn":11},{"ruleId":"prefer-const","severity":1,"message":"'sandbox' is never reassigned. Use 'const' instead.","line":5,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":5,"endColumn":10},{"ruleId":"prefer-const","severity":1,"message":"'returnUrl' is never reassigned. Use 'const' instead.","line":6,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":12},{"ruleId":"prefer-const","severity":1,"message":"'widgetScript' is never reassigned. Use 'const' instead.","line":7,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":7,"endColumn":15},{"ruleId":"prefer-const","severity":1,"message":"'loginScript' is never reassigned. Use 'const' instead.","line":8,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":8,"endColumn":14},{"ruleId":"prefer-const","severity":1,"message":"'failPage' is never reassigned. Use 'const' instead.","line":9,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":9,"endColumn":11},{"ruleId":"prefer-const","severity":1,"message":"'isRecurring' is never reassigned. Use 'const' instead.","line":10,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":10,"endColumn":14},{"ruleId":"prefer-const","severity":1,"message":"'validTokenPattern' is never reassigned. Use 'const' instead.","line":14,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":14,"endColumn":20},{"ruleId":"prefer-regex-literals","severity":1,"message":"Use a regular expression literal instead of the 'RegExp' constructor.","line":14,"column":23,"nodeType":"NewExpression","messageId":"unexpectedRegExp","endLine":14,"endColumn":44,"suggestions":[{"messageId":"replaceWithLiteral","fix":{"range":[598,619],"text":"/^Atza/"},"desc":"Replace with an equivalent regular expression literal."}]},{"ruleId":"prefer-const","severity":1,"message":"'CARD_SELECT_DELAY' is never reassigned. Use 'const' instead.","line":22,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":22,"endColumn":20},{"ruleId":"prefer-const","severity":1,"message":"'accessToken' is never reassigned. Use 'const' instead.","line":98,"column":2,"nodeType":"Identifier","messageId":"useConst","endLine":98,"endColumn":13},{"ruleId":"prefer-const","severity":1,"message":"'loginError' is never reassigned. Use 'const' instead.","line":99,"column":2,"nodeType":"Identifier","messageId":"useConst","endLine":99,"endColumn":12},{"ruleId":"mediawiki/no-cookie","severity":1,"message":"Avoid direct access to document.cookie. Use mw.cookie instead.","line":129,"column":12,"nodeType":"Identifier","messageId":"noCookie","endLine":129,"endColumn":18},{"ruleId":"no-jquery/no-sizzle","severity":1,"message":"Selector extensions are not allowed","line":268,"column":8,"nodeType":"CallExpression","endLine":268,"endColumn":45}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":15,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*global amazon:true, OffAmazonPayments:true*/\n( function ( $, mw ) {\n\tlet clientId = mw.config.get( 'wgAmazonGatewayClientID' ),\n\t\tsellerId = mw.config.get( 'wgAmazonGatewaySellerID' ),\n\t\tsandbox = mw.config.get( 'wgAmazonGatewaySandbox' ),\n\t\treturnUrl = mw.config.get( 'wgAmazonGatewayReturnURL' ),\n\t\twidgetScript = mw.config.get( 'wgAmazonGatewayWidgetScript' ),\n\t\tloginScript = mw.config.get( 'wgAmazonGatewayLoginScript' ),\n\t\tfailPage = mw.config.get( 'wgAmazonGatewayFailPage' ),\n\t\tisRecurring = $( '#recurring' ).val(),\n\t\tloggedIn = false,\n\t\tloginError,\n\t\taccessToken,\n\t\tvalidTokenPattern = new RegExp( '^Atza' ),\n\t\tbillingAgreementId,\n\t\torderReferenceId,\n\t\trecurConsentGranted = false,\n\t\tcardSelected = false,\n\t\tcardSelectTimeout,\n\t\t// If no card selected after this long, show link to other ways to give\n\t\t// in case the donor has no cards registered with Amazon\n\t\tCARD_SELECT_DELAY = 5000;\n\n\t$( () => {\n\t\t// Add a couple divs to hold the widgets\n\t\t$( '.submethods' ).before(\n\t\t\t'<div id=\"consentWidget\" />' +\n\t\t\t'<div id=\"walletWidget\" />' +\n\t\t\t'<div id=\"amazonLogin\" />'\n\t\t);\n\t\t// Set the click handler\n\t\t$( '#paymentSubmitBtn' ).click( submitPayment );\n\t} );\n\n\t// Adapted from Amazon documentation, will get parameters from fragment as\n\t// well as querystring and accepts Amazon's custom delimiters\n\tfunction getURLParameter( name, source ) {\n\t\tconst pattern = '[?&#]' + name + '=([^&;#]*)',\n\t\t\tmatches = new RegExp( pattern ).exec( source ) || [ '', '' ],\n\t\t\tvalue = matches[ 1 ].replace( /\\+/g, '%20' );\n\n\t\treturn decodeURIComponent( value ) || null;\n\t}\n\n\tfunction loadScript( url ) {\n\t\tconst a = document.createElement( 'script' );\n\t\ta.type = 'text/javascript';\n\t\ta.async = true;\n\t\ta.src = url;\n\t\tdocument.head.appendChild( a );\n\t}\n\n\tfunction redirectToLogin() {\n\t\t$( '#overlay' ).show();\n\t\tconst loginOptions = {\n\t\t\tscope: 'payments:widget',\n\t\t\tpopup: false\n\t\t};\n\t\tamazon.Login.authorize( loginOptions, returnUrl );\n\t}\n\n\tfunction addErrorMessage( message ) {\n\t\t$( '#topError' ).append(\n\t\t\t$( '<p class=\"error\">' + message + '</p>' )\n\t\t);\n\t\t$( '#errorReference' )\n\t\t\t.removeClass( 'errorMsgHide' )\n\t\t\t.addClass( 'errorMsg' );\n\t}\n\n\tfunction reloadPage() {\n\t\tconst qsParams = $( '#payment-form' ).serializeArray();\n\t\tdocument.location.replace( mw.util.getUrl( 'Special:AmazonGateway', qsParams ) );\n\t}\n\n\tfunction showErrorAndLoginButton( message ) {\n\t\tif ( message ) {\n\t\t\taddErrorMessage( message );\n\t\t}\n\t\tOffAmazonPayments.Button(\n\t\t\t'amazonLogin',\n\t\t\tsellerId,\n\t\t\t{\n\t\t\t\ttype: 'PwA',\n\t\t\t\tcolor: 'Gold',\n\t\t\t\tsize: 'large',\n\t\t\t\tauthorization: reloadPage\n\t\t\t}\n\t\t);\n\t}\n\n\tfunction tokenExpired() {\n\t\t// Re-create widget so it displays timeout error message\n\t\tcreateWalletWidget();\n\t\tshowErrorAndLoginButton();\n\t}\n\n\taccessToken = getURLParameter( 'access_token', location.hash );\n\tloginError = getURLParameter( 'error', location.search );\n\n\t// This will be called as soon as the login script is loaded\n\twindow.onAmazonLoginReady = function () {\n\n\t\tamazon.Login.setClientId( clientId );\n\t\tamazon.Login.setUseCookie( true );\n\t\tamazon.Login.setSandboxMode( sandbox );\n\t\tif ( !loggedIn ) {\n\t\t\tif ( loginError ) {\n\t\t\t\tshowErrorAndLoginButton(\n\t\t\t\t\tgetURLParameter( 'error_description', location.search )\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tredirectToLogin();\n\t\t\t}\n\t\t}\n\t};\n\n\twindow.onAmazonPaymentsReady = function () {\n\t\tlet tokenLifetime;\n\t\tif ( loggedIn ) {\n\t\t\ttokenLifetime = parseInt( getURLParameter( 'expires_in', location.hash ), 10 );\n\t\t\tcreateWalletWidget();\n\t\t\tsetTimeout( tokenExpired, tokenLifetime * 1000 );\n\t\t}\n\t};\n\n\tif ( typeof accessToken === 'string' && accessToken.match( validTokenPattern ) ) {\n\t\t// Payment widgets need this cookie\n\t\tdocument.cookie = 'amazon_Login_accessToken=' + accessToken + ';secure';\n\t\tloggedIn = true;\n\t\tloadScript( widgetScript ); // This will load the login script for you\n\t} else {\n\t\tif ( loginError ) {\n\t\t\t// Load the full widget script to display a button\n\t\t\tloadScript( widgetScript );\n\t\t} else {\n\t\t\t// The first time around, only load the login script.\n\t\t\tloadScript( loginScript );\n\t\t}\n\t}\n\n\tfunction showOtherWaysLink() {\n\t\tconst url = mw.config.get( 'wgAmazonGatewayOtherWaysURL' ),\n\t\t\ttext = mw.message( 'donate_interface-otherways-short' );\n\t\taddErrorMessage( '<a href=\"' + url + '\">' + text + '</a>' );\n\t}\n\n\tfunction setSubmitVisibility() {\n\t\tlet show = true;\n\t\tif ( !cardSelected ) {\n\t\t\tshow = false;\n\t\t}\n\t\tif ( isRecurring && !recurConsentGranted ) {\n\t\t\tshow = false;\n\t\t}\n\t\tif ( show ) {\n\t\t\t$( '#paymentSubmit' ).show();\n\t\t} else {\n\t\t\t$( '#paymentSubmit' ).hide();\n\t\t}\n\t}\n\n\tfunction createWalletWidget() {\n\t\tconst params = {\n\t\t\tsellerId: sellerId,\n\t\t\tonReady: function ( billingAgreement ) {\n\t\t\t\tif ( !cardSelected ) {\n\t\t\t\t\tcardSelectTimeout = setTimeout( showOtherWaysLink, CARD_SELECT_DELAY );\n\t\t\t\t}\n\t\t\t\tif ( !billingAgreementId ) {\n\t\t\t\t\tbillingAgreementId = billingAgreement.getAmazonBillingAgreementId();\n\t\t\t\t\tif ( isRecurring ) {\n\t\t\t\t\t\tcreateConsentWidget();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tagreementType: isRecurring ? 'BillingAgreement' : 'OrderReference',\n\t\t\tonOrderReferenceCreate: function ( orderReference ) {\n\t\t\t\tif ( orderReferenceId ) {\n\t\t\t\t\t// Redisplaying for an existing order, no need to continue\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\torderReferenceId = orderReference.getAmazonOrderReferenceId();\n\t\t\t},\n\t\t\tonPaymentSelect: function () {\n\t\t\t\tif ( !cardSelected ) {\n\t\t\t\t\tcardSelected = true;\n\t\t\t\t\tsetSubmitVisibility();\n\t\t\t\t}\n\t\t\t\tif ( cardSelectTimeout ) {\n\t\t\t\t\tclearTimeout( cardSelectTimeout );\n\t\t\t\t\tcardSelectTimeout = false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdesign: {\n\t\t\t\tdesignMode: 'responsive'\n\t\t\t},\n\t\t\tonError: function ( error ) {\n\t\t\t\t// Error message appears directly in widget\n\t\t\t\tshowErrorAndLoginButton();\n\t\t\t}\n\t\t};\n\t\t// If we are refreshing the widget to display a correctable error,\n\t\t// we need to set the Amazon order reference ID for continuity\n\t\tif ( orderReferenceId ) {\n\t\t\tparams.amazonOrderReferenceId = orderReferenceId;\n\t\t}\n\t\tif ( billingAgreementId ) {\n\t\t\tparams.amazonBillingAgreementId = billingAgreementId;\n\t\t}\n\t\tnew OffAmazonPayments.Widgets.Wallet( params ).bind( 'walletWidget' );\n\t}\n\n\tfunction handleConsentStatus( billingAgreementConsentStatus ) {\n\t\t// getConsentStatus returns a string for some reason\n\t\trecurConsentGranted =\n\t\t\t( billingAgreementConsentStatus.getConsentStatus() === 'true' );\n\t\tsetSubmitVisibility();\n\t}\n\n\tfunction createConsentWidget() {\n\t\tconst params = {\n\t\t\tsellerId: sellerId,\n\t\t\tamazonBillingAgreementId: billingAgreementId,\n\t\t\tdesign: {\n\t\t\t\tdesignMode: 'responsive'\n\t\t\t},\n\t\t\tonReady: handleConsentStatus,\n\t\t\tonConsent: handleConsentStatus,\n\t\t\tonError: function ( error ) {\n\t\t\t\tshowErrorAndLoginButton();\n\t\t\t}\n\t\t};\n\t\t$( '#consentWidget' ).show();\n\t\tnew OffAmazonPayments.Widgets.Consent( params ).bind( 'consentWidget' );\n\t}\n\n\tfunction handleErrors( errors ) {\n\t\tlet code,\n\t\t\trefreshWallet = false;\n\n\t\tfor ( code in errors ) {\n\t\t\tif ( !Object.prototype.hasOwnProperty.call( errors, code ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( code === 'token-mismatch' ) {\n\t\t\t\t// Session has expired, we need to reload the whole page.\n\t\t\t\t// FIXME: something nicer than an alert box\n\t\t\t\talert( errors[ code ] );\n\t\t\t\treloadPage();\n\t\t\t}\n\t\t\taddErrorMessage( errors[ code ] );\n\t\t\tif ( code === 'InvalidPaymentMethod' ) {\n\t\t\t\t// Card declined, but they can try another\n\t\t\t\trefreshWallet = true;\n\t\t\t}\n\t\t}\n\n\t\tif ( refreshWallet ) {\n\t\t\t// Redisplay the widget to show an error and let the donor pick a different card\n\t\t\tcardSelected = false;\n\t\t\tsetSubmitVisibility();\n\t\t\tcreateWalletWidget();\n\t\t}\n\t}\n\n\tfunction lockDonationAmount() {\n\t\tif ( $( '#amount_input' ).is( ':visible' ) ) {\n\t\t\t$( '#amount_input' ).hide();\n\t\t\t$( '#selected-amount' )\n\t\t\t\t.text( $( '#amount' ).val() + ' ' + $( '#currency' ).val() )\n\t\t\t\t.show();\n\t\t}\n\t}\n\n\tfunction submitPayment() {\n\t\tif ( !mw.donationInterface.validation.validateAmount() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( !cardSelected ) {\n\t\t\tshowOtherWaysLink();\n\t\t\treturn;\n\t\t}\n\t\tif ( isRecurring && !recurConsentGranted ) {\n\t\t\t//TODO: error message\n\t\t\treturn;\n\t\t}\n\t\t$( '#topError' ).html( '' );\n\t\t$( '#errorReference' )\n\t\t\t.removeClass( 'errorMsg' )\n\t\t\t.addClass( 'errorMsgHide' );\n\t\t$( '#overlay' ).show();\n\t\tlockDonationAmount();\n\t\tconst postdata = {\n\t\t\taction: 'di_amazon_bill',\n\t\t\tformat: 'json',\n\t\t\trecurring: isRecurring,\n\t\t\tamount: $( '#amount' ).val(),\n\t\t\tcurrency: $( '#currency' ).val(),\n\t\t\twmf_token: $( '#wmf_token' ).val()\n\t\t};\n\n\t\tif ( isRecurring ) {\n\t\t\tpostdata.billingAgreementId = billingAgreementId;\n\t\t} else {\n\t\t\tpostdata.orderReferenceId = orderReferenceId;\n\t\t}\n\n\t\t$.ajax( {\n\t\t\turl: mw.util.wikiScript( 'api' ),\n\t\t\tdata: postdata,\n\t\t\tdataType: 'json',\n\t\t\ttype: 'POST',\n\t\t\tsuccess: function ( data ) {\n\t\t\t\tif ( data.errors ) {\n\t\t\t\t\t$( '#overlay' ).hide();\n\t\t\t\t\thandleErrors( data.errors );\n\t\t\t\t} else if ( data.redirect ) {\n\t\t\t\t\tlocation.href = data.redirect;\n\t\t\t\t} else {\n\t\t\t\t\tlocation.href = failPage;\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function () {\n\t\t\t\tlocation.href = failPage;\n\t\t\t}\n\t\t} );\n\t}\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/braintree_gateway/forms/braintree.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'di' is never reassigned. Use 'const' instead.","line":10,"column":6,"nodeType":"Identifier","messageId":"useConst","endLine":10,"endColumn":8},{"ruleId":"prefer-const","severity":1,"message":"'payment_method' is never reassigned. Use 'const' instead.","line":12,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":12,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'scripts' is never reassigned. Use 'const' instead.","line":13,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":13,"endColumn":10}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*global braintree:true, paypal:true*/\n( function ( $, mw ) {\n\t/* Paypal iFrame comes with a zIndex of 100. Inorder to stack the autocomplete\n\tmenu above the Paypal button, we need to set the zIndex to be at least a step higher.\n\tThe mediawiki library for the menu item sets the autocomplete menu zIndex to 1 step higher\n\tthan the parents zIndex here: resources/lib/jquery.ui/jquery.ui.autocomplete.js::484\n\t */\n\t$( '#employer' ).css( { position: 'relative', zIndex: 100 } );\n\n\tlet di = mw.donationInterface,\n\t\tmyDeviceData,\n\t\tpayment_method = $( '#payment_method' ).val(),\n\t\tscripts = mw.config.get( 'scriptsToLoad' );\n\n\t$( '.submethods' ).before( '<div id=\"' + payment_method + '-button\"></div>' );\n\n\tfunction handleApiResult( result ) {\n\t\tif ( result.isFailed ) {\n\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceFailUrl' ) );\n\t\t} else if ( mw.monthlyConvert && mw.monthlyConvert.canShowModal() ) {\n\t\t\tmw.monthlyConvert.init();\n\t\t} else {\n\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceThankYouPage' ) );\n\t\t}\n\t}\n\n\tfunction showClientSideErrorMessage( msg ) {\n\t\t$( '.errorMsg' ).remove();\n\t\t$( '#errorReference' ).html( '' );\n\t\t$( '#topError' ).html( msg );\n\t}\n\n\tfunction getPaymentMethodUsage() {\n\t\treturn $( '#recurring' ).val() === '1' ? 'multi_use' : 'single_use';\n\t}\n\n\tfunction getAmountValue() {\n\t\treturn $.trim( $( '#amount' ).val() );\n\t}\n\n\tfunction createBraintreeClient() {\n\t\treturn braintree.client.create( {\n\t\t\tauthorization: mw.config.get( 'clientToken' )\n\t\t} );\n\t}\n\n\tfunction createVenmoInstance( braintreeClientInstance ) {\n\t\treturn braintree.venmo.create( getVenmoCreateOptions( braintreeClientInstance ) );\n\t}\n\n\tfunction getVenmoCreateOptions( braintreeClientInstance ) {\n\t\treturn {\n\t\t\tclient: braintreeClientInstance,\n\t\t\tallowDesktop: true,\n\t\t\tmobileWebFallBack: true,\n\t\t\tallowNewBrowserTab: true,\n\t\t\tallowDesktopWebLogin: true, // force web login, QR code depreciate\n\t\t\tpaymentMethodUsage: getPaymentMethodUsage(),\n\t\t\ttotalAmount: getAmountValue()\n\t\t};\n\t}\n\n\tfunction buildVenmoSendData( payload ) {\n\t\tconst sendData = {\n\t\t\tpayment_token: payload.nonce,\n\t\t\tdevice_data: myDeviceData,\n\t\t\tuser_name: payload.details.username,\n\t\t\tgateway_session_id: payload.details.paymentContextId\n\t\t};\n\n\t\t// payload.details.payerInfo is undefined for non-us sandbox account\n\t\tif ( payload.details.payerInfo ) {\n\t\t\tsendData.first_name = payload.details.payerInfo.firstName;\n\t\t\tsendData.last_name = payload.details.payerInfo.lastName;\n\t\t\tsendData.phone = payload.details.payerInfo.phoneNumber;\n\t\t\tsendData.email = payload.details.payerInfo.email;\n\t\t\tsendData.street_address = payload.details.payerInfo.shippingAddress;\n\t\t\tsendData.customer_id = payload.details.payerInfo.externalId;\n\t\t}\n\n\t\treturn sendData;\n\t}\n\n\tfunction handleVenmoError( err ) {\n\t\tif ( err && err.code === 'VENMO_CANCELED' ) {\n\t\t\tshowClientSideErrorMessage( 'App is not available or user aborted payment flow' );\n\t\t} else if ( err && err.code === 'VENMO_APP_CANCELED' ) {\n\t\t\tshowClientSideErrorMessage( 'User canceled payment flow' );\n\t\t} else {\n\t\t\tshowClientSideErrorMessage( err && err.message ? err.message : String( err ) );\n\t\t}\n\t}\n\n\tfunction handleVenmoSuccess( payload ) {\n\t\tdi.forms.callDonateApi(\n\t\t\thandleApiResult, buildVenmoSendData( payload ), 'di_donate_braintree'\n\t\t);\n\t}\n\n\tfunction displayVenmoButton( braintreeClientInstance ) {\n\t\tconst venmoButton = document.getElementById( 'venmo-button' );\n\t\tif ( !venmoButton ) {\n\t\t\tshowClientSideErrorMessage( 'Venmo button element not found' );\n\t\t\treturn;\n\t\t}\n\n\t\tvenmoButton.style.display = 'block';\n\t\tvenmoButton.addEventListener( 'click', () => {\n\t\t\tvenmoButton.disabled = true;\n\n\t\t\tcreateVenmoInstance( braintreeClientInstance ).then( ( venmoInstance ) => {\n\t\t\t\tif ( !venmoInstance.isBrowserSupported() ) {\n\t\t\t\t\tshowClientSideErrorMessage( 'Browser does not support Venmo' );\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn venmoInstance.tokenize();\n\t\t\t} ).then( ( payload ) => {\n\t\t\t\tif ( payload ) {\n\t\t\t\t\thandleVenmoSuccess( payload );\n\t\t\t\t}\n\t\t\t} ).catch( handleVenmoError ).then( () => {\n\t\t\t\tvenmoButton.removeAttribute( 'disabled' );\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// myDeviceData will supply device data for non-recurring vault trxns\n\t// see https://developer.paypal.com/braintree/docs/guides/paypal/vault#collecting-device-data\n\t// https://developer.paypal.com/braintree/docs/guides/premium-fraud-management-tools/device-data-collection/javascript/v3/#collecting-device-data\n\tfunction getDeviceData( braintreeClientInstance ) {\n\t\tbraintree.dataCollector.create( {\n\t\t\tclient: braintreeClientInstance\n\t\t} ).then( ( dataCollectorInstance ) => {\n\t\t\t// At this point, you should access the dataCollectorInstance.deviceData value and provide it\n\t\t\t// to your server, e.g. by injecting it into your form as a hidden input\n\t\t\tmyDeviceData = dataCollectorInstance.deviceData;\n\t\t} ).catch( ( err ) => {\n\t\t\tshowClientSideErrorMessage( 'Device data error' + err );\n\t\t} );\n\t}\n\n\tfunction setup() {\n\t\tif ( payment_method === 'paypal' ) {\n\t\t\tcreateBraintreeClient().then( ( braintreeClientInstance ) => {\n\t\t\t\tgetDeviceData( braintreeClientInstance );\n\t\t\t\t// Create a PayPal Checkout component.\n\t\t\t\treturn braintree.paypalCheckout.create( {\n\t\t\t\t\tclient: braintreeClientInstance\n\t\t\t\t} );\n\t\t\t} ).then( ( paypalCheckoutInstance ) => paypalCheckoutInstance.loadPayPalSDK( {\n\t\t\t\tvault: true\n\t\t\t} ) ).then( ( paypalCheckoutInstance ) => paypal.Buttons( {\n\t\t\t\tfundingSource: paypal.FUNDING.PAYPAL,\n\n\t\t\t\tcreateBillingAgreement: function () {\n\t\t\t\t\treturn paypalCheckoutInstance.createPayment( {\n\t\t\t\t\t\tflow: 'vault' // Required\n\t\t\t\t\t} );\n\t\t\t\t},\n\n\t\t\t\tonApprove: function ( data, actions ) {\n\t\t\t\t\treturn paypalCheckoutInstance.tokenizePayment( data ).then( ( payload ) => {\n\t\t\t\t\t\tconst sendData = {\n\t\t\t\t\t\t\tpayment_token: payload.nonce,\n\t\t\t\t\t\t\tdevice_data: myDeviceData,\n\t\t\t\t\t\t\tfirst_name: payload.details.firstName,\n\t\t\t\t\t\t\tlast_name: payload.details.lastName,\n\t\t\t\t\t\t\temail: payload.details.email,\n\t\t\t\t\t\t\tstreet_address: payload.details.shippingAddress\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tdi.forms.callDonateApi(\n\t\t\t\t\t\t\thandleApiResult, sendData, 'di_donate_braintree'\n\t\t\t\t\t\t);\n\t\t\t\t\t} );\n\t\t\t\t},\n\n\t\t\t\tonCancel: function ( data ) {\n\t\t\t\t\tshowClientSideErrorMessage( 'PayPal payment canceled' + JSON.stringify( data, 0, 2 ) );\n\t\t\t\t},\n\n\t\t\t\tonError: function ( err ) {\n\t\t\t\t\tshowClientSideErrorMessage( 'PayPal error' + err );\n\t\t\t\t}\n\t\t\t} ).render( '#paypal-button' ) ).then( () => {\n\t\t\t\t// The PayPal button will be rendered in an html element with the ID\n\t\t\t\t// `paypal-button`. This function will be called when the PayPal button\n\t\t\t\t// is set up and ready to be used\n\t\t\t} ).catch( ( err ) => {\n\t\t\t\t// Handle component creation error\n\t\t\t\tshowClientSideErrorMessage( 'component creation error: ' + err );\n\t\t\t} );\n\t\t} else if ( payment_method === 'venmo' ) {\n\t\t\tcreateBraintreeClient().then( ( braintreeClientInstance ) => {\n\t\t\t\tgetDeviceData( braintreeClientInstance );\n\t\t\t\tdisplayVenmoButton( braintreeClientInstance );\n\t\t\t} ).catch( ( err ) => {\n\t\t\t\tshowClientSideErrorMessage( 'Error creating Venmo:' + err );\n\t\t\t} );\n\t\t}\n\t}\n\n\t// loadScript (called internally) will display an error message when a\n\t// script fails to load, so we just suppress any rejections with an\n\t// empty catch block here.\n\tmw.donationInterface.forms.loadScriptsInOrder( scripts )\n\t\t.then( setup )\n\t\t.catch( () => {} );\n\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/composer.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/dlocal_gateway/forms/dlocal.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'dlocalInstance' is never reassigned. Use 'const' instead.","line":27,"column":7,"nodeType":"Identifier","messageId":"useConst","endLine":27,"endColumn":21},{"ruleId":"prefer-const","severity":1,"message":"'fields' is never reassigned. Use 'const' instead.","line":28,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":28,"endColumn":10},{"ruleId":"prefer-const","severity":1,"message":"'commonStyle' is never reassigned. Use 'const' instead.","line":33,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":33,"endColumn":15},{"ruleId":"prefer-const","severity":1,"message":"'cardField' is never reassigned. Use 'const' instead.","line":49,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":49,"endColumn":12},{"ruleId":"prefer-const","severity":1,"message":"'expirationField' is never reassigned. Use 'const' instead.","line":55,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":55,"endColumn":18},{"ruleId":"prefer-const","severity":1,"message":"'cvvField' is never reassigned. Use 'const' instead.","line":61,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":61,"endColumn":11}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*global dlocal:true*/\n( function ( $, mw ) {\n\tconst country = $( '#country' ).val(),\n\t\textraData = {},\n\t\tisRecurring = !!$( '#recurring' ).val(),\n\t\tisIndia = ( country === 'IN' );\n\n\tfunction handleApiResult( result ) {\n\t\tif ( result.isFailed ) {\n\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t} );\n\t\t} else if ( mw.monthlyConvert && mw.monthlyConvert.canShowModal() ) {\n\t\t\tmw.monthlyConvert.init();\n\t\t} else if ( result.redirect ) {\n\t\t\tdocument.location.replace( result.redirect );\n\t\t} else {\n\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceThankYouPage' ) );\n\t\t}\n\t}\n\n\tfunction showPaymentSubmit() {\n\t\t$( '#paymentSubmit' ).show();\n\t}\n\n\tfunction setupCardForm() {\n\t\tlet dlocalInstance = dlocal( mw.config.get( 'wgDlocalSmartFieldApiKey' ) ),\n\t\t\tfields = dlocalInstance.fields( {\n\t\t\t\tlocale: mapLang( $( '#language' ).val() ),\n\t\t\t\tcountry: country\n\t\t\t} ),\n\t\t\t// Custom styling can be passed to options when creating a Smart Field.\n\t\t\tcommonStyle = getCardCommonStyle(),\n\t\t\tcardField,\n\t\t\tcardFieldError = false,\n\t\t\tcardFieldSupportError = false,\n\t\t\tcardFieldEmpty = true,\n\t\t\texpirationField,\n\t\t\texpirationFieldError = false,\n\t\t\texpirationFieldEmpty = true,\n\t\t\tcvvField,\n\t\t\tcvvFieldError = false,\n\t\t\tcvvFieldEmpty = true;\n\n\t\tinsertBrazilRecurringAdvice();\n\t\taddCardFieldsToErrorDisplay();\n\n\t\t// create card fields and add events\n\t\tcardField = fields.create( 'pan', {\n\t\t\tstyle: commonStyle,\n\t\t\tplaceholder: '4111 1111 1111 1111'\n\t\t} );\n\t\taddCardFieldEvents();\n\n\t\texpirationField = fields.create( 'expiration', {\n\t\t\tstyle: commonStyle,\n\t\t\tplaceholder: mw.msg( 'donate_interface-expiry-date-field-placeholder' )\n\t\t} );\n\t\taddExpirationFieldEvents();\n\n\t\tcvvField = fields.create( 'cvv', {\n\t\t\tstyle: commonStyle,\n\t\t\tplaceholder: '123',\n\t\t\tmaskInput: true\n\t\t} );\n\t\taddCvvFieldEvents();\n\n\t\t// Show our standard 'Donate' button\n\t\tshowPaymentSubmit();\n\t\t// Set the click handler\n\t\t// Using debounce to prevent the programmatic trigger of multiple instances of the submit function\n\t\t$( '#paymentSubmitBtn' ).click( mw.util.debounce( handleCardSubmitClick, 100 ) );\n\n\t\t// Drop in the dlocal card components placeholder\n\t\tinsertCardComponentContainers();\n\n\t\tcardField.mount( document.getElementById( 'cardNumber' ) );\n\t\texpirationField.mount( document.getElementById( 'expiration' ) );\n\t\tcvvField.mount( document.getElementById( 'cvv' ) );\n\n\t\tfunction addCardFieldEvents() {\n\t\t\tcardField.addEventListener( 'change', ( event ) => {\n\t\t\t\tcardFieldError = !!event.error;\n\t\t\t\tif ( event.error ) {\n\t\t\t\t\t$( '#cardNumberErrorMsg' ).text( mw.msg( 'donate_interface-error-msg-unsupported-card-entered' ) );\n\t\t\t\t} else {\n\t\t\t\t\t$( '#cardNumberErrorMsg' ).text( '' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tcardField.on( 'blur', ( event ) => {\n\t\t\t\tcardFieldEmpty = event.empty;\n\t\t\t} );\n\n\t\t\tcardField.on( 'brand', ( event ) => {\n\t\t\t\t// after input 6 number, ready to check bin\n\t\t\t\tif ( event.brand ) {\n\t\t\t\t\tdlocalInstance.getBinInformation( cardField ).then( ( res ) => {\n\t\t\t\t\t\tconst binInfoCardBrand = res.brand;\n\t\t\t\t\t\tconst cardBrand = mw.config.get( 'codeMap' )[ binInfoCardBrand ];\n\t\t\t\t\t\tif ( cardBrand !== undefined ) {\n\t\t\t\t\t\t\tcardFieldSupportError = false;\n\t\t\t\t\t\t\textraData.payment_submethod = cardBrand;\n\t\t\t\t\t\t\t$( '#cardNumberErrorMsg' ).text( '' );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcardFieldSupportError = true;\n\t\t\t\t\t\t\t$( '#credit-card-wrapper' ).addClass( 'DlocalField--invalid' );\n\t\t\t\t\t\t\t$( '#cardNumberErrorMsg' ).text( mw.msg( 'donate_interface-error-msg-unsupported-card-entered' ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t} ).catch( ( error ) => {\n\t\t\t\t\t\t// Suppress bin lookup error.\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tfunction addExpirationFieldEvents() {\n\t\t\texpirationField.addEventListener( 'change', ( event ) => {\n\t\t\t\texpirationFieldError = !!event.error;\n\t\t\t\tif ( event.error ) {\n\t\t\t\t\t$( '#expirationErrorMsg' ).text( mw.msg( 'donate_interface-error-msg-card-too-old' ) );\n\t\t\t\t} else {\n\t\t\t\t\t$( '#expirationErrorMsg' ).text( '' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\texpirationField.on( 'blur', ( event ) => {\n\t\t\t\texpirationFieldEmpty = event.empty;\n\t\t\t} );\n\t\t}\n\n\t\tfunction addCvvFieldEvents() {\n\t\t\tcvvField.addEventListener( 'change', ( event ) => {\n\t\t\t\tcvvFieldError = !!event.error;\n\t\t\t\tif ( event.error ) {\n\t\t\t\t\t$( '#cvvErrorMsg' ).text( mw.msg( 'donate_interface-error-msg-invalid-cvv-format' ) );\n\t\t\t\t} else {\n\t\t\t\t\t$( '#cvvErrorMsg' ).text( '' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tcvvField.on( 'blur', ( event ) => {\n\t\t\t\tcvvFieldEmpty = event.empty;\n\t\t\t} );\n\t\t}\n\n\t\tfunction validateInputs() {\n\t\t\tconst formValid = mw.donationInterface.validation.validate(),\n\t\t\t\tcvvFieldHasErrors = cvvFieldError || cvvFieldEmpty,\n\t\t\t\tcardFieldHasErrors = cardFieldError || cardFieldEmpty || cardFieldSupportError,\n\t\t\t\texpFieldHasErrors = expirationFieldError || expirationFieldEmpty,\n\t\t\t\terrors = {};\n\n\t\t\tif ( !formValid || cvvFieldHasErrors || cardFieldHasErrors || expFieldHasErrors ) {\n\t\t\t\tif ( cardFieldHasErrors ) {\n\t\t\t\t\tif ( cardFieldEmpty ) {\n\t\t\t\t\t\terrors.cardNumber = mw.msg( 'donate_interface-error-msg-card-num' );\n\t\t\t\t\t} else if ( cardFieldSupportError ) {\n\t\t\t\t\t\terrors.cardNumber = mw.msg( 'donate_interface-error-msg-unsupported-card-entered' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.cardNumber = mw.msg( 'donate_interface-error-msg-invalid-card-number' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( cvvFieldHasErrors ) {\n\t\t\t\t\tif ( cvvFieldEmpty ) {\n\t\t\t\t\t\terrors.cvv = mw.msg( 'donate_interface-error-msg-cvv' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.cvv = mw.msg( 'donate_interface-error-msg-invalid-cvv-format' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( expFieldHasErrors ) {\n\t\t\t\t\tif ( expirationFieldEmpty ) {\n\t\t\t\t\t\terrors.expiration = mw.msg( 'donate_interface-error-msg-expiration' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.expiration = mw.msg( 'donate_interface-error-msg-card-too-old' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmw.donationInterface.validation.showErrors( errors );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction handleCardSubmitClick( event ) {\n\t\t\tif ( $( this ).is( ':disabled' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tmw.donationInterface.forms.disable();\n\n\t\t\tif ( validateInputs() ) {\n\t\t\t\tdlocalInstance.createToken( cardField, {\n\t\t\t\t\tname: $( '#first_name' ).val() + ' ' + $( '#last_name' ).val()\n\t\t\t\t} ).then( ( result ) => {\n\t\t\t\t\t// Send the token to your server.\n\t\t\t\t\textraData.fiscal_number = $( '#fiscal_number' ).val();\n\t\t\t\t\textraData.payment_token = result.token;\n\t\t\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\t\t\thandleApiResult,\n\t\t\t\t\t\textraData,\n\t\t\t\t\t\t'di_donate_dlocal'\n\t\t\t\t\t);\n\t\t\t\t} ).catch( ( result ) => {\n\t\t\t\t\tif ( result.error ) {\n\t\t\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Helper functions for card form setup that do not need to be inside the setup function's scope\n\tfunction insertBrazilRecurringAdvice() {\n\t\tif ( country === 'BR' && isRecurring ) {\n\t\t\t$( '.submethods' ).before( $( '<p>' +\n\t\t\t\tmw.msg( 'donate_interface-monthly-only-credit' ) +\n\t\t\t\t'</p>' ) );\n\t\t}\n\t}\n\n\t// https://docs.dlocal.com/reference/the-dlocal-object#dlocalfieldsoptions\n\t// Supported values are: es, en, pt, zh, cv, tr.\n\tfunction mapLang( wikiLang ) {\n\t\tif ( wikiLang === 'es-419' ) {\n\t\t\treturn 'es';\n\t\t} else if ( [ 'es', 'en', 'pt', 'zh', 'cv', 'tr' ].includes( wikiLang ) ) {\n\t\t\treturn wikiLang;\n\t\t} else {\n\t\t\t// todo: maybe display an error, or just default en?\n\t\t\treturn 'en';\n\t\t}\n\t}\n\n\tfunction addCardFieldsToErrorDisplay() {\n\t\tconst oldShowErrors = mw.donationInterface.validation.showErrors;\n\t\tmw.donationInterface.validation.showErrors = function ( errors ) {\n\t\t\tmw.donationInterface.forms.enable();\n\t\t\tconst dLocalFields = [ 'cardNumber', 'expiration', 'cvv' ];\n\t\t\t$.each( errors, ( field ) => {\n\t\t\t\tif ( dLocalFields.includes( field ) ) {\n\t\t\t\t\t$( '#' + field ).find( '.DlocalField' ).addClass( 'DlocalField--invalid' );\n\t\t\t\t\t$( '#' + field + 'ErrorMsg' ).text( errors[ field ] );\n\t\t\t\t\tdelete errors[ field ];\n\t\t\t\t}\n\t\t\t} );\n\t\t\toldShowErrors( errors );\n\t\t};\n\t}\n\n\tfunction insertCardComponentContainers() {\n\t\t$( '.submethods' ).before(\n\t\t\t'<div>' +\n\t\t\t'<label for=\"cardNumber\">' + mw.message( 'donate_interface-donor-card-num' ) + '</label>' +\n\t\t\t'<div id=\"cardNumber\" ></div>' +\n\t\t\t'<span class=\"DlocalField--invalid-text\" id=\"cardNumberErrorMsg\" />' +\n\t\t\t'</div>' +\n\t\t\t'<div>' +\n\t\t\t'<div class=\"halfwidth\">' +\n\t\t\t'<label for=\"expiration\">' + mw.message( 'donate_interface-donor-expiration' ) + '</label>' +\n\t\t\t'<div id=\"expiration\" ></div>' +\n\t\t\t'<span class=\"DlocalField--invalid-text\" id=\"expirationErrorMsg\"></span>' +\n\t\t\t'</div>' +\n\t\t\t'<div class=\"halfwidth\">' +\n\t\t\t'<label for=\"cvv\">' + mw.message( 'donate_interface-cvv' ) + '</label>' +\n\t\t\t'<div id=\"cvv\"></div>' +\n\t\t\t'<span class=\"DlocalField--invalid-text\" id=\"cvvErrorMsg\"></span>' +\n\t\t\t'</div>' +\n\t\t\t'</div>'\n\t\t);\n\t}\n\n\tfunction getCardCommonStyle() {\n\t\treturn {\n\t\t\tbase: {\n\t\t\t\tfontSize: '14px',\n\t\t\t\t\tfontFamily: 'sans-serif',\n\t\t\t\t\tlineHeight: '40px',\n\t\t\t\t\tfontSmoothing: 'antialiased',\n\t\t\t\t\tfontWeight: '500',\n\t\t\t\t\tcolor: 'rgb(0, 17, 44)',\n\t\t\t\t\t'::placeholder': {\n\t\t\t\t\tcolor: 'rgb(185, 196, 201)'\n\t\t\t\t}\n\t\t\t},\n\t\t\tfocus: {\n\t\t\t\ticonColor: '#adbfd3',\n\t\t\t\t\t'::placeholder': {\n\t\t\t\t\tcolor: '#adbfd3'\n\t\t\t\t}\n\t\t\t},\n\t\t\tautofilled: {\n\t\t\t\tcolor: '#000000'\n\t\t\t},\n\t\t\tinvalid: {\n\t\t\t\tcolor: '#f00'\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction setupNonCardForm() {\n\t\tconst upiRecurringIsOnDemand = mw.config.get( 'isOnDemand' ),\n\t\t\tisDirectPaymentFlow = mw.config.get( 'isDirectPaymentFlow' ),\n\t\t\t// 'paytmwallet' submethod should be treated as the same for upi\n\t\t\tisUpi = new RegExp( '\\\\b' + $( 'input[name=payment_submethod]:checked' ).val() + '\\\\b', 'i' ).test( 'upi paytmwallet' ); // i is case insensitive\n\n\t\tif ( isUpi && isRecurring && upiRecurringIsOnDemand ) {\n\t\t\t// If we are using the ONDEMAND charge frequency, add a note to reassure donors\n\t\t\t// that we will only charge them once a month\n\t\t\t$( '.submethods' ).after( $( '<p>' +\n\t\t\t\tmw.msg( 'donate_interface-charge-monthly-only' ) +\n\t\t\t\t'</p>' ) );\n\t\t}\n\n\t\tif ( isDirectPaymentFlow ) {\n\t\t\t// Show our standard 'Donate' button\n\t\t\tshowPaymentSubmit();\n\t\t\t// only non-recurring upi is direct, and it must IN and bt, so no needs to check those two val\n\t\t\tif ( isUpi && !isRecurring ) {\n\t\t\t\taddUpiDirectFlowInputField();\n\t\t\t\t// Set the click handler\n\t\t\t\t$( '#paymentSubmitBtn' ).click( mw.util.debounce( handleUpiDirectSubmitClick, 100 ) );\n\t\t\t}\n\t\t} else {\n\t\t\t// Redirect flow\n\t\t\t$( '.submethods' ).after(\n\t\t\t\t$( '<p id=\"redirect-explanation\">' + mw.message( 'donate_interface-redirect-explanation' ) + '</p>' )\n\t\t\t);\n\t\t}\n\t}\n\n\t// Support functions for non-card form setup\n\tfunction addUpiDirectFlowInputField() {\n\t\t$( '.submethods' ).before(\n\t\t\t$( '<label for=\"upi_id\">' +\n\t\t\t\tmw.msg( 'donate_interface-bt-upi_id' ) +\n\t\t\t\t'</label>' +\n\t\t\t\t'<input value=\"\" name=\"upi_id\" id=\"upi_id\" />' ) );\n\t}\n\n\tfunction handleUpiDirectSubmitClick( event ) {\n\t\tif ( $( this ).is( ':disabled' ) ) {\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\t// Disable submit btn when submitting\n\t\tmw.donationInterface.forms.disable();\n\t\t// get verify\n\t\textraData.fiscal_number = $( '#fiscal_number' ).val();\n\t\textraData.upi_id = $( '#upi_id' ).val();\n\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\thandleApiResult,\n\t\t\textraData,\n\t\t\t'di_donate_dlocal'\n\t\t);\n\t}\n\n\t/**\n\t *  On document ready we create a script tag and wire it up to run setup as soon as it\n\t *  is loaded, or to show an error message if the external script can't be loaded.\n\t *  The script should already be mostly or completely preloaded at this point, thanks\n\t *  to a <link rel=preload> we add in DlocalGateway::execute\n\t */\n\t$( () => {\n\t\tif ( isIndia ) {\n\t\t\t$( '#fiscal_number' ).after(\n\t\t\t\t$( '<p style=\"font-size: 10px\">' + mw.msg( 'donate_interface-donor-fiscal_number-explain-option-in' ) +\n\t\t\t\t\t'</p>' )\n\t\t\t);\n\t\t}\n\t\t// only cc load smart field script and submit button, others show redirect with continue button\n\t\tif ( $( '#payment_method' ).val() === 'cc' ) {\n\t\t\tconst scriptNode = document.createElement( 'script' );\n\t\t\tscriptNode.onload = setupCardForm;\n\t\t\tscriptNode.onerror = function () {\n\t\t\t\tmw.donationInterface.validation.showErrors(\n\t\t\t\t\t{ general: 'Could not load payment provider Javascript. Please reload or try again later.' }\n\t\t\t\t);\n\t\t\t};\n\t\t\tscriptNode.src = mw.config.get( 'dlocalScript' );\n\t\t\tdocument.body.append( scriptNode );\n\t\t} else {\n\t\t\tsetupNonCardForm();\n\t\t}\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/extension.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/gravy_gateway/forms/gravy.js","messages":[{"ruleId":"no-shadow","severity":1,"message":"'appleSession' is already declared in the upper scope on line 14 column 3.","line":454,"column":43,"nodeType":"Identifier","messageId":"noShadow","endLine":454,"endColumn":55}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global SecureFields google ApplePaySession ApplePayError */\n( function ( $, mw ) {\n\tlet secureFieldValid = false,\n\t\tcardNumberFieldValid = false,\n\t\tsecurityCodeValid = false,\n\t\texpiryDateValid = false,\n\t\tcardNumberFieldEmpty = true,\n\t\tsecurityCodeFieldEmpty = true,\n\t\texpiryDateFieldEmpty = true,\n\t\tsecureFields = null,\n\t\tcardScheme = null,\n\t\textraData = {},\n\t\tgooglePaymentClient = null,\n\t\tappleSession = null;\n\n\tconst configFromServer = mw.config.get( 'gravyConfiguration' ),\n\t\tsessionId = mw.config.get( 'gravy_session_id' ),\n\t\tenvironment = mw.config.get( 'wgGravyEnvironment' ),\n\t\tgravyId = mw.config.get( 'wgGravyId' ),\n\t\tredirectPaypal = mw.config.get( 'wgGravyRedirectPaypal' ),\n\t\tshowRedirectText = mw.config.get( 'showRedirectText' ),\n\t\tlanguage = $( '#language' ).val(),\n\t\tcountry = $( '#country' ).val(),\n\t\tisIndia = ( country === 'IN' ),\n\t\tapplePayPaySessionVersionNumber = 3, // https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_on_the_web_version_history\n\t\tdi = mw.donationInterface;\n\n\tfunction insertCardComponentContainers() {\n\t\t$( '.submethods' ).before(\n\t\t\t'<div>' +\n\t\t\t'<label for=\"cc-number\">' + mw.message( 'donate_interface-donor-card-num' ) + '</label>' +\n\t\t\t'<input id=\"cc-number\" />' +\n\t\t\t'<span class=\"GravyField--invalid-text\" id=\"cardNumberErrorMsg\" />' +\n\t\t\t'</div>' +\n\t\t\t'<div>' +\n\t\t\t'<div class=\"halfwidth\">' +\n\t\t\t'<label for=\"cc-expiry-date\">' + mw.message( 'donate_interface-donor-expiration' ) + '</label>' +\n\t\t\t'<input id=\"cc-expiry-date\" />' +\n\t\t\t'<span class=\"GravyField--invalid-text\" id=\"expirationErrorMsg\"></span>' +\n\t\t\t'</div>' +\n\t\t\t'<div class=\"halfwidth\">' +\n\t\t\t'<label for=\"cc-security-code\">' + mw.message( 'donate_interface-donor-security' ) + '</label>' +\n\t\t\t'<input id=\"cc-security-code\" />' +\n\t\t\t'<span class=\"GravyField--invalid-text\" id=\"cvvErrorMsg\"></span>' +\n\t\t\t'</div>' +\n\t\t\t'</div>'\n\t\t);\n\t}\n\n\tfunction ccInputEmptyStyle( id, evt ) {\n\t\tif ( !evt.empty ) {\n\t\t\tsetFieldError( id ,evt.valid, false );\n\t\t} else {\n\t\t\t$( id ).removeAttr( 'data-secure-fields-invalid' );\n\t\t}\n\t}\n\n\tfunction setupCardFields() {\n\t\tconst inputStyle = {\n\t\t\tfontSize: '16px',\n\t\t\tpadding: '5px 8px',\n\t\t\tinvalidColor: 'unset'\n\t\t};\n\t\tconst cardNumberField = secureFields.addCardNumberField( '#cc-number', {\n\t\t\t\tplaceholder: '1234 5678 9012 3456',\n\t\t\t\tstyles: inputStyle\n\t\t\t} );\n\n\t\tconst securityCodeField = secureFields.addSecurityCodeField( '#cc-security-code', {\n\t\t\t\tplaceholder: mw.msg( 'donate_interface-cvv-placeholder-3-digits' ),\n\t\t\t\tstyles: inputStyle\n\t\t\t} );\n\n\t\tconst expiryDateField = secureFields.addExpiryDateField( '#cc-expiry-date', {\n\t\t\t\tplaceholder: mw.msg( 'donate_interface-expiry-date-field-placeholder' ),\n\t\t\t\tstyles: inputStyle\n\t\t\t} );\n\t\t// based on card type show logo and update cvv placeholder when amex\n\t\tcardNumberField.addEventListener( 'input', ( evt ) => {\n\t\t\tif ( evt.schema ) {\n\t\t\t\tcardScheme = evt.schema;\n\t\t\t\t//change logo where appropriate\n\t\t\t\tconst iconUrl = 'https://api.' + gravyId + '.gr4vy.app/assets/icons/card-schemes/' + evt.schema + '.svg';\n\t\t\t\t$( '#cc-number' ).css( 'background-image', 'url(' + iconUrl + ')' );\n\t\t\t\tif ( evt.schema === 'amex' ) {\n\t\t\t\t\tsecurityCodeField.setPlaceholder( mw.msg( 'donate_interface-cvv-placeholder-4-digits' ) );\n\t\t\t\t} else {\n\t\t\t\t\tsecurityCodeField.setPlaceholder( mw.msg( 'donate_interface-cvv-placeholder-3-digits' ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( evt.bin ) {\n\t\t\t\tdi.forms.setBinHash( evt.bin );\n\t\t\t}\n\t\t\tccInputEmptyStyle( '#cc-number', evt );\n\t\t} );\n\t\texpiryDateField.addEventListener( 'input', ( evt ) => {\n\t\t\t// for error icon\n\t\t\t$( '#cc-expiry-date' ).toggleClass( 'valid-input', !evt.empty && evt.valid );\n\t\t\tccInputEmptyStyle( '#cc-expiry-date', evt );\n\t\t} );\n\t\tsecurityCodeField.addEventListener( 'input', ( evt ) => {\n\t\t\t// for error icon\n\t\t\t$( '#cc-security-code' ).toggleClass( 'valid-input', !evt.empty && evt.valid );\n\t\t\tccInputEmptyStyle( '#cc-security-code', evt );\n\t\t} );\n\t}\n\n\tfunction setFieldError( fieldId, isValid, isEmpty, altMsgKey ) {\n\t\tlet errorMsg = '', errorMsgId, errorMsgKey, emptyMsgKey;\n\t\tswitch ( fieldId ) {\n\t\t\tcase '#cc-number':\n\t\t\t\terrorMsgId = '#cardNumberErrorMsg';\n\t\t\t\terrorMsgKey = 'donate_interface-error-msg-invalid-card-number';\n\t\t\t\temptyMsgKey = 'donate_interface-error-msg-card-num';\n\t\t\t\tbreak;\n\t\t\tcase '#cc-expiry-date':\n\t\t\t\terrorMsgId = '#expirationErrorMsg';\n\t\t\t\terrorMsgKey = 'donate_interface-error-msg-expiry-date-field-invalid';\n\t\t\t\temptyMsgKey = 'donate_interface-error-msg-expiration';\n\t\t\t\tbreak;\n\t\t\tcase '#cc-security-code':\n\t\t\t\terrorMsgId = '#cvvErrorMsg';\n\t\t\t\terrorMsgKey = 'donate_interface-error-msg-invalid-cvv-format';\n\t\t\t\temptyMsgKey = 'donate_interface-error-msg-cvv';\n\t\t\t\tbreak;\n\t\t}\n\t\t$( fieldId ).toggleClass( 'GravyField--invalid invalid-input', !isValid || isEmpty );\n\t\tif ( altMsgKey ) {\n\t\t\terrorMsg = mw.msg( altMsgKey );\n\t\t} else if ( !isValid || isEmpty ) {\n\t\t\terrorMsg = isEmpty ? mw.msg( emptyMsgKey ) : mw.msg( errorMsgKey );\n\t\t}\n\t\t$( errorMsgId ).text( errorMsg );\n\t}\n\n\tfunction setupCardForm() {\n\t\tsecureFields = new SecureFields( {\n\t\t\tgr4vyId: gravyId,\n\t\t\tenvironment: environment,\n\t\t\tsessionId: sessionId,\n\t\t\tstyles: {\n\t\t\t\tfontSize: '16px',\n\t\t\t\tpadding: '0.8em',\n\t\t\t\tbackgroundColor: '#fff',\n\t\t\t\tborderRadius: '2px',\n\t\t\t\tborder: '1px solid #a2a9b1',\n\t\t\t\tcolor: '#000',\n\t\t\t\tfontFamily: 'inherit',\n\t\t\t\tlineHeight: '17px',\n\t\t\t\tmarginBottom: '0.2em'\n\t\t\t},\n\t\t\ttheme: {\n\t\t\t\tcolors: {\n\t\t\t\t\tinputBorder: '#a2a9b1'\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tsecureFields.addEventListener( SecureFields.Events.CARD_VAULT_SUCCESS, () => {\n\t\t\tset3DSecureBrowserInfo();\n\t\t\textraData.fiscal_number = $( '#fiscal_number' ).val();\n\t\t\textraData.gateway_session_id = sessionId;\n\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\thandleApiResult,\n\t\t\t\textraData,\n\t\t\t\t'di_donate_gravy'\n\t\t\t);\n\t\t} );\n\n\t\tsecureFields.addEventListener(\n\t\t\tSecureFields.Events.CARD_VAULT_FAILURE,\n\t\t\t() => {\n\t\t\t\tmw.donationInterface.forms.addDebugMessage( 'Card vault failure on gravy checkout session id: ' + sessionId );\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t} );\n\t\t\t\tmw.donationInterface.forms.enable();\n\t\t\t}\n\t\t);\n\n\t\tsecureFields.addEventListener(\n\t\t\tSecureFields.Events.FORM_CHANGE,\n\t\t\t( data ) => {\n\t\t\t\tif ( data ) {\n\t\t\t\t\tsecureFieldValid = data.complete;\n\t\t\t\t\tif ( data.fields ) {\n\t\t\t\t\t\tcardNumberFieldEmpty = data.fields.number.empty;\n\t\t\t\t\t\tcardNumberFieldValid = data.fields.number.valid;\n\t\t\t\t\t\texpiryDateFieldEmpty = data.fields.expiryDate.empty;\n\t\t\t\t\t\texpiryDateValid = data.fields.expiryDate.valid;\n\t\t\t\t\t\tsecurityCodeFieldEmpty = data.fields.securityCode.empty;\n\t\t\t\t\t\tsecurityCodeValid = data.fields.securityCode.valid;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tinsertCardComponentContainers();\n\t\tsetupCardFields();\n\n\t\t$( '#paymentSubmit' ).show();\n\t\t$( '#paymentSubmitBtn' ).click( mw.util.debounce( handleCardSubmitClick, 100 ) );\n\t}\n\n\tfunction validateInputs() {\n\t\tif ( !mw.donationInterface.validation.validate() || !secureFieldValid ) {\n\t\t\tsetFieldError( '#cc-number', cardNumberFieldValid, cardNumberFieldEmpty );\n\t\t\tsetFieldError( '#cc-security-code', securityCodeValid, securityCodeFieldEmpty );\n\t\t\tsetFieldError( '#cc-expiry-date', expiryDateValid, expiryDateFieldEmpty );\n\t\t\treturn false;\n\t\t}\n\t\t// AmEx is not supported in India\n\t\tif ( cardScheme === 'amex' && isIndia ) {\n\t\t\tsetFieldError( '#cc-number', true, false, 'donate_interface-error-msg-unsupported-card-entered' );\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tfunction handleCardSubmitClick( event ) {\n\t\tif ( $( this ).is( ':disabled' ) ) {\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tmw.donationInterface.forms.disable();\n\n\t\tif ( validateInputs() ) {\n\t\t\tsecureFields.submit();\n\t\t} else {\n\t\t\tmw.donationInterface.forms.enable();\n\t\t}\n\t}\n\n\tfunction handleApiResult( result ) {\n\t\tif ( result.isFailed ) {\n\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceFailUrl' ) );\n\t\t} else if ( result.redirect ) {\n\t\t\tdocument.location.replace( result.redirect );\n\t\t} else if ( mw.monthlyConvert && mw.monthlyConvert.canShowModal() ) {\n\t\t\t// Extra guard against unintended duplicate donations: before showing the monthly convert\n\t\t\t// modal, neuter di.forms.submit() so it just sends donors to the TY page. We have seen\n\t\t\t// some donors dismiss the monthly convert modal and somehow remain on the page to click\n\t\t\t// submit again, even multiple times.\n\t\t\tdi.forms.submit = function () {\n\t\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceThankYouPage' ) );\n\t\t\t};\n\t\t\tmw.monthlyConvert.init();\n\t\t} else {\n\t\t\tdocument.location.replace( mw.config.get( 'DonationInterfaceThankYouPage' ) );\n\t\t}\n\t}\n\n\tfunction set3DSecureBrowserInfo() {\n\t\tconst browserInfo = {\n\t\t\tcolor_depth: screen.colorDepth || 24,\n\t\t\tscreen_height: screen.height || 0,\n\t\t\tscreen_width: screen.width || 0,\n\t\t\ttime_zone_offset: Math.floor( new Date().getTimezoneOffset() ) || 0\n\t\t};\n\n\t\tfor ( const key in browserInfo ) {\n\t\t\textraData[ key ] = browserInfo[ key ];\n\t\t}\n\t}\n\n\tfunction insertGooglePayComponentContainer() {\n\t\tif ( document.getElementById( 'googlepay-container' ) ) {\n\t\t\treturn;\n\t\t}\n\t\t$( '.submethods' ).before(\n\t\t\t'<div id=\"googlepay-container\"></div>'\n\t\t);\n\t}\n\n\tfunction handleGooglePayButtonClick() {\n\t\tconst paymentRequest = getGooglepayRequest(),\n\t\t\tgooglePayClient = getGooglePayClient();\n\n\t\tgooglePayClient.loadPaymentData( paymentRequest ).then( ( paymentData ) => {\n\t\t\tconst paymentToken = paymentData.paymentMethodData.tokenizationData.token,\n\t\t\t\tdonorInfo = paymentData.paymentMethodData.info.billingAddress;\n\n\t\t\textraData.postal_code = donorInfo.postalCode;\n\t\t\textraData.state_province = donorInfo.administrativeArea;\n\t\t\textraData.city = donorInfo.locality;\n\t\t\textraData.street_address = donorInfo.address1;\n\t\t\textraData.email = paymentData.email;\n\t\t\textraData.full_name = donorInfo.name;\n\t\t\textraData.payment_token = paymentToken;\n\t\t\textraData.card_suffix = paymentData.paymentMethodData.info.cardDetails;\n\t\t\textraData.card_scheme = paymentData.paymentMethodData.info.cardNetwork;\n\t\t\tmw.donationInterface.forms.disable();\n\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\thandleApiResult,\n\t\t\t\textraData,\n\t\t\t\t'di_donate_gravy'\n\t\t\t);\n\t\t} ).catch( ( err ) => {\n\t\t\tmw.donationInterface.forms.addDebugMessage( 'Google Pay failure: ' + err );\n\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t} );\n\t\t\tmw.donationInterface.forms.enable();\n\t\t} );\n\t}\n\n\tfunction getGoogleBaseRequest() {\n\t\treturn {\n\t\t\tapiVersion: 2,\n\t\t\tapiVersionMinor: 0\n\t\t};\n\t}\n\n\tfunction getGoogleBaseCardPaymentMethod() {\n\t\tconst allowedCardNetworks = configFromServer.googleAllowedNetworks;\n\t\tconst allowedCardAuthMethods = [ 'PAN_ONLY', 'CRYPTOGRAM_3DS' ];\n\t\treturn {\n\t\t\ttype: 'CARD',\n\t\t\tparameters: {\n\t\t\t\tallowedCardNetworks: allowedCardNetworks,\n\t\t\t\tallowedAuthMethods: allowedCardAuthMethods,\n\t\t\t\tbillingAddressRequired: true,\n\t\t\t\tbillingAddressParameters: {\n\t\t\t\t\tformat: 'FULL'\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction getGoogleTransactionInfo() {\n\t\treturn {\n\t\t\ttotalPriceStatus: 'FINAL',\n\t\t\ttotalPrice: $( '#amount' ).val(),\n\t\t\tcurrencyCode: $( '#currency' ).val(),\n\t\t\tcountryCode: country\n\t\t};\n\t}\n\n\tfunction clearApplePaySessionAndEnableButton() {\n\t\tappleSession = null;\n\t\tconst btn = document.getElementById( 'applepay-btn' );\n\t\tif ( btn ) {\n\t\t\tbtn.disabled = false;\n\t\t}\n\t}\n\n\tfunction getGoogleMerchantInfo() {\n\t\treturn {\n\t\t\tmerchantName: 'WikimediaFoundation',\n\t\t\tmerchantId: configFromServer.googleMerchantId\n\t\t};\n\t}\n\n\tfunction getGooglepayRequest() {\n\t\tconst paymentRequest = getGoogleBaseRequest();\n\t\tconst cardPaymentMethod = getGoogleBaseCardPaymentMethod();\n\t\tconst gravyGooglePayMerchantId = configFromServer.gravyGooglePayMerchantId;\n\t\tconst tokenizationSpecification = {\n\t\t\ttype: 'PAYMENT_GATEWAY',\n\t\t\tparameters: {\n\t\t\t\tgateway: 'gr4vy',\n\t\t\t\tgatewayMerchantId: gravyGooglePayMerchantId\n\t\t\t}\n\t\t};\n\t\tcardPaymentMethod.tokenizationSpecification = tokenizationSpecification;\n\t\tpaymentRequest.allowedPaymentMethods = [ cardPaymentMethod ];\n\t\tpaymentRequest.transactionInfo = getGoogleTransactionInfo();\n\t\tpaymentRequest.merchantInfo = getGoogleMerchantInfo();\n\n\t\tpaymentRequest.emailRequired = true;\n\n\t\treturn paymentRequest;\n\t}\n\n\tfunction getGoogleIsReadyToPayRequest() {\n\t\tconst request = getGoogleBaseRequest();\n\t\tconst baseCardPaymentMethod = getGoogleBaseCardPaymentMethod();\n\t\trequest.allowedPaymentMethods = [ baseCardPaymentMethod ];\n\t\treturn request;\n\t}\n\n\tfunction getGooglePayClient() {\n\t\tif ( googlePaymentClient === null ) {\n\t\t\tgooglePaymentClient = new google.payments.api.PaymentsClient( { environment: configFromServer.googleEnvironment } );\n\t\t}\n\t\treturn googlePaymentClient;\n\t}\n\n\tfunction setupGooglePayForm() {\n\t\tinsertGooglePayComponentContainer();\n\t\tconst googlePayClient = getGooglePayClient();\n\t\tconst isReadyToPayRequest = getGoogleIsReadyToPayRequest();\n\t\tgooglePayClient\n\t\t\t.isReadyToPay( isReadyToPayRequest )\n\t\t\t.then( ( response ) => {\n\t\t\t\tif ( response && response.result ) {\n\t\t\t\t\tconst button = googlePayClient.createButton( {\n\t\t\t\t\t\tonClick: mw.util.debounce( () => {\n\t\t\t\t\t\t\thandleGooglePayButtonClick();\n\t\t\t\t\t\t}, 100 ),\n\t\t\t\t\t\tallowedPaymentMethods: [ 'CARD', 'TOKENIZED_CARD' ],\n\t\t\t\t\t\tbuttonType: 'donate'\n\t\t\t\t\t} );\n\t\t\t\t\tdocument.getElementById( 'googlepay-container' ).appendChild( button );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( err ) => {\n\t\t\t\tmw.donationInterface.forms.addDebugMessage( 'Google Pay failure: ' + err );\n\t\t\t} );\n\t}\n\n\tfunction setupApplePayForm() {\n\t\t// Check apple pay availability before showing button\n\t\tif ( window.ApplePaySession ) {\n\t\t\tinsertApplePayComponentContainer();\n\t\t\tconst button = document.getElementById( 'applepay-btn' );\n\t\t\tbutton.addEventListener( 'click', handleApplePaySubmitClick );\n\t\t} else {\n\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\tgeneral: mw.message(\n\t\t\t\t\t'donate_interface-error-msg-apple_pay_unsupported',\n\t\t\t\t\tmw.config.get( 'DonationInterfaceOtherWaysURL' )\n\t\t\t\t).plain()\n\t\t\t} );\n\t\t\tmw.donationInterface.forms.addDebugMessage( 'Apple Pay failure: Unable to find ApplePaySession in browser' );\n\t\t}\n\t}\n\n\tfunction handleApplePayApiResult( result ) {\n\t\tif ( appleSession ) {\n\t\t\tappleSession.completePayment( {\n\t\t\t\tstatus: ApplePaySession.STATUS_SUCCESS\n\t\t\t} );\n\t\t\tappleSession = null;\n\t\t}\n\n\t\thandleApiResult( result );\n\t}\n\n\tfunction handleApplePaySubmitClick( e ) {\n\t\te.preventDefault();\n\t\tconst button = e.currentTarget;\n\n\t\t// Prevent double-tap / double session\n\t\tif ( appleSession || button.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tbutton.disabled = true;\n\t\tsetupApplePaySession();\n\t\tappleSession.begin();\n\t}\n\n\tfunction validateApplePayPaymentSession( appleSession ) {\n\t\treturn function ( event ) {\n\t\t\tconst api = new mw.Api();\n\t\t\tapi.post( {\n\t\t\t\taction: 'di_applesession_gravy',\n\t\t\t\tvalidation_url: event.validationURL,\n\t\t\t\twmf_token: $( '#wmf_token' ).val()\n\t\t\t} ).then( ( data ) => {\n\t\t\t\tif ( data.result && data.result.errors ) {\n\t\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t\t} );\n\t\t\t\t\tclearApplePaySessionAndEnableButton();\n\t\t\t\t\tmw.donationInterface.forms.addDebugMessage( 'Apple Pay failure: ' + data.result.errors );\n\t\t\t\t} else {\n\t\t\t\t\tappleSession.completeMerchantValidation( data.session );\n\t\t\t\t}\n\t\t\t} ).catch( ( e ) => {\n\t\t\t\tappleSession.abort();\n\t\t\t\tclearApplePaySessionAndEnableButton();\n\t\t\t\tmw.donationInterface.forms.addDebugMessage( 'Apple Pay failure: ' + e );\n\t\t\t\tmw.donationInterface.validation.showErrors( {\n\t\t\t\t\tgeneral: mw.msg( 'donate_interface-error-msg-general' )\n\t\t\t\t} );\n\t\t\t} );\n\t\t};\n\t}\n\n\tfunction setupApplePaySession() {\n\t\tconst paymentRequestObject = {\n\t\t\tcountryCode: country,\n\t\t\tcurrencyCode: $( '#currency' ).val(),\n\t\t\tmerchantCapabilities: [ 'supportsCredit', 'supportsDebit', 'supports3DS' ],\n\t\t\tsupportedNetworks: [ 'visa', 'masterCard', 'amex', 'discover' ],\n\t\t\trequiredBillingContactFields: [ 'email', 'name', 'phone', 'postalAddress' ],\n\t\t\trequiredShippingContactFields: [ 'email', 'name' ],\n\t\t\ttotal: {\n\t\t\t\tlabel: 'Wikimedia Foundation',\n\t\t\t\ttype: 'final',\n\t\t\t\tamount: $( '#amount' ).val()\n\t\t\t}\n\t\t};\n\t\tappleSession = new ApplePaySession( applePayPaySessionVersionNumber, paymentRequestObject );\n\t\tappleSession.oncancel = function () {\n\t\t\tclearApplePaySessionAndEnableButton();\n\t\t};\n\t\tappleSession.onvalidatemerchant = validateApplePayPaymentSession( appleSession );\n\n\t\tappleSession.onpaymentauthorized = function ( event ) {\n\t\t\tconst bContact = event.payment.billingContact,\n\t\t\t\tsContact = event.payment.shippingContact;\n\t\t\tlet paymentSubmethod = event.payment.token.paymentMethod.network;\n\t\t\tif ( !paymentSubmethod ) {\n\t\t\t\tpaymentSubmethod = '';\n\t\t\t}\n\t\t\textraData = mw.donationInterface.forms.apple.getBestApplePayContactName( extraData, bContact, sContact );\n\t\t\textraData.postal_code = bContact.postalCode;\n\t\t\textraData.state_province = bContact.administrativeArea;\n\t\t\textraData.city = bContact.locality;\n\t\t\tif ( Array.isArray( bContact.addressLines ) && bContact.addressLines.length > 0 ) {\n\t\t\t\textraData.street_address = bContact.addressLines[ 0 ];\n\t\t\t}\n\t\t\textraData.email = sContact.emailAddress;\n\t\t\textraData.payment_submethod = paymentSubmethod.toLowerCase();\n\t\t\textraData.payment_token = JSON.stringify( event.payment.token );\n\n\t\t\tconst applePayErrors = getApplePayErrors();\n\t\t\tif ( applePayErrors.length === 0 ) {\n\t\t\t\tmw.donationInterface.forms.callDonateApi(\n\t\t\t\t\thandleApplePayApiResult,\n\t\t\t\t\textraData,\n\t\t\t\t\t'di_donate_gravy'\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// First and last name not configured in ApplePay sheet.\n\t\t\t\t// Show errors in payment sheet\n\t\t\t\tconst response = {\n\t\t\t\t\tstatus: ApplePaySession.STATUS_FAILURE,\n\t\t\t\t\terrors: applePayErrors\n\t\t\t\t};\n\t\t\t\tappleSession.completePayment( response );\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction insertApplePayComponentContainer() {\n\t\t$( '.submethods' ).before(\n\t\t\t'<div id=\"applepay-container\">' +\n\t\t\t'<apple-pay-button class=\"button\" id=\"applepay-btn\" buttonstyle=\"black\" type=\"donate\" locale=\"' + language + '\"></apple-pay-button>' +\n\t\t\t'</div>'\n\t\t);\n\t}\n\n\tfunction getApplePayErrors() {\n\t\tconst applePayErrors = [];\n\t\tif ( !extraData.first_name || !extraData.first_name.trim() ) {\n\t\t\tapplePayErrors.push( new ApplePayError(\n\t\t\t\t'billingContactInvalid',\n\t\t\t\t'name',\n\t\t\t\tmw.msg( 'donate_interface-error-msg-first_name' )\n\t\t\t) );\n\t\t}\n\t\tif ( !extraData.last_name || !extraData.last_name.trim() ) {\n\t\t\tapplePayErrors.push( new ApplePayError(\n\t\t\t\t'billingContactInvalid',\n\t\t\t\t'name',\n\t\t\t\tmw.msg( 'donate_interface-error-msg-last_name' )\n\t\t\t) );\n\t\t}\n\t\tif ( !extraData.email || !extraData.email.trim() ) {\n\t\t\tapplePayErrors.push( new ApplePayError(\n\t\t\t\t'shippingContactInvalid',\n\t\t\t\t'email',\n\t\t\t\tmw.msg( 'donate_interface-error-msg-email' )\n\t\t\t) );\n\t\t}\n\t\treturn applePayErrors;\n\t}\n\n\tfunction submitPaypal() {\n\n\t\tfunction redirect( result ) {\n\t\t\t// We don't actually want to enable the form on redirect or in the\n\t\t\t// complete phase of callDonateApi, so we override enable here.\n\t\t\tdi.forms.enable = function () {};\n\t\t\tlocation.assign( result.redirect );\n\t\t}\n\n\t\tdi.forms.submit = function () {\n\t\t\t// MediaWiki uses the \"uselang\" parameter to set the language for localization\n\t\t\t// Checkout /payments/includes/api/ApiMain.php\n\t\t\tdi.forms.callDonateApi( redirect, { uselang: $( '#language' ).val() } );\n\t\t};\n\n\t\tdi.forms.submit();\n\t}\n\n\tfunction setUpSepa() {\n\t\t$( '#paymentSubmit' ).show();\n\t\t$( '#paymentSubmitBtn' ).click( mw.util.debounce( ( evt ) => {\n\t\t\tmw.donationInterface.forms.validateAndSubmit( evt );\n\t\t}, 100 ) );\n\t}\n\n\t/**\n\t *  On document ready we create a script tag and wire it up to run setup as soon as it\n\t *  is loaded, or to show an error message if the external script can't be loaded.\n\t *  The script should already be mostly or completely preloaded at this point, thanks\n\t *  to a <link rel=preload> we add in GravyGateway::execute.\n\t *  Don't try to load the script if the configured src is empty (as happens on the\n\t *  resultSwitcher where we may show the monthly convert modal).\n\t */\n\t$( () => {\n\t\tif ( isIndia ) {\n\t\t\t$( '#fiscal_number' ).after(\n\t\t\t\t$( '<p style=\"font-size: 10px\">' + mw.msg( 'donate_interface-donor-fiscal_number-explain-option-in' ) +\n\t\t\t\t\t'</p>' )\n\t\t\t);\n\t\t}\n\t\tswitch ( $( '#payment_method' ).val() ) {\n\t\t\tcase 'cc':\n\t\t\t\t// loadScript will display an error message when the script fails to load\n\t\t\t\t// so we just suppress the rejection with an empty catch block here.\n\t\t\t\tmw.donationInterface.forms.loadScript( configFromServer.secureFieldsJsScript )\n\t\t\t\t\t.then( setupCardForm )\n\t\t\t\t\t.catch( () => {} );\n\t\t\t\tbreak;\n\t\t\tcase 'google':\n\t\t\t\tmw.donationInterface.forms.loadScript( configFromServer.googleScript )\n\t\t\t\t\t.then( setupGooglePayForm )\n\t\t\t\t\t.catch( () => {} );\n\t\t\t\tbreak;\n\t\t\tcase 'apple':\n\t\t\t\tmw.donationInterface.forms.loadScript( configFromServer.appleScript )\n\t\t\t\t\t.then( setupApplePayForm )\n\t\t\t\t\t.catch( () => {} );\n\t\t\t\tbreak;\n\t\t\tcase 'paypal':\n\t\t\t\tif ( redirectPaypal && !di.validation.hasErrors() ) {\n\t\t\t\t\tsubmitPaypal();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'rtbt':\n\t\t\t\tsetUpSepa();\n\t\t}\n\t\tif ( showRedirectText ) {\n\t\t\t// Redirect flow\n\t\t\t$( '.submethods' ).after(\n\t\t\t\t$( '<p id=\"redirect-explanation\">' + mw.message( 'donate_interface-redirect-explanation' ) + '</p>' )\n\t\t\t);\n\t\t}\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/ingenico_gateway/forms/js/ingenico.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/jest.config.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/jest.setup.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/ApiUtils.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":13,"column":16,"nodeType":"MemberExpression","messageId":"forbidden","endLine":13,"endColumn":29}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"function apiPost( params ) {\n\treturn ( new mw.Api() ).post( params );\n}\n\nconst apiRecurringPostAction = function ( recurringContributionRecord, params, actionName ) {\n\tconst donorData = mw.config.get( 'donorData' );\n\tlet requestBody = {\n\t\tcontact_id: Number( donorData.contact_id ),\n\t\tchecksum: donorData.checksum,\n\t\tcontribution_recur_id: Number( recurringContributionRecord.id ),\n\t\taction: actionName\n\t};\n\trequestBody = Object.assign( {}, requestBody, params );\n\trecurringContributionRecord.is_processing = true;\n\treturn apiPost( requestBody );\n};\n\nfunction requestRecurringPause( recurringContributionRecord, params ) {\n\treturn apiRecurringPostAction( recurringContributionRecord, params, 'requestPauseRecurring' );\n}\n\nfunction requestRecurringCancel( recurringContributionRecord, params ) {\n\treturn apiRecurringPostAction( recurringContributionRecord, params, 'requestCancelRecurring' );\n}\n\nfunction requestRecurringUpdate( recurringContributionRecord, params ) {\n\treturn apiRecurringPostAction( recurringContributionRecord, params, 'requestUpdateRecurring' );\n}\n\nfunction requestAnnualConversion( recurringContributionRecord, params ) {\n\treturn apiRecurringPostAction( recurringContributionRecord, params, 'requestAnnualConversion' );\n}\n\nfunction requestNewChecksumLink( email, page, subpage ) {\n\tconst params = {\n\t\temail: email,\n\t\taction: 'requestNewChecksumLink',\n\t\tpage: page\n\t};\n\tif ( subpage ) {\n\t\tparams.subpage = subpage;\n\t}\n\treturn apiPost( params );\n}\n\nmodule.exports = {\n\trequestRecurringPause,\n\trequestRecurringCancel,\n\trequestRecurringUpdate,\n\trequestNewChecksumLink,\n\trequestAnnualConversion\n};\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/App.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsDisclaimerComponent.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":4,"column":34,"nodeType":"VAttribute","messageId":"unexpected","endLine":4,"endColumn":62},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":6,"column":34,"nodeType":"VAttribute","messageId":"unexpected","endLine":6,"endColumn":56}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<div class=\"dp-table__disclaimer\">\n\t\t<p class=\"text text--body\">\n\t\t\t<span class=\"text text--body\" v-html=\"donationsDisclaimer\"></span>\n\t\t\t<br><br>\n\t\t\t<span class=\"text text--body\" v-html=\"taxDisclaimer\"></span>\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nmodule.exports = exports = defineComponent( {\n\tname: 'DonationsDisclaimerComponent',\n    props: {\n        email: {\n            type: String,\n            required: true,\n            default: 'N/A'\n        },\n        helpEmail: {\n            type: String,\n            required: true\n        }\n    },\n    computed: {\n        donationsDisclaimer: function () {\n            return this.$i18n( 'donorportal-donations-disclaimer', this.email, `<a href=\"mailto:${ this.helpEmail }\" class=\"link\">${ this.helpEmail }</a>` ).text();\n        },\n        taxDisclaimer: function () {\n            return this.$i18n( 'donorportal-tax-disclaimer', `<a href=\"mailto:${ this.helpEmail }\" class=\"link\">${ this.helpEmail }</a>` ).text();\n        }\n    }\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsHistory.vue","messages":[{"ruleId":"no-shadow","severity":1,"message":"'panel' is already declared in the upper scope on line 138 column 10.","line":128,"column":25,"nodeType":"Identifier","messageId":"noShadow","endLine":128,"endColumn":30}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<!-- Donation History -->\n\t<section id=\"donorportal-donation-history\" class=\"dp-card\">\n\t\t<div class=\"dp-card__head\">\n\t\t\t{{ $i18n( \"donorportal-your-donation-history\" ).text() }}\n\t\t</div>\n\t\t<!-- Codex Component: Tabs -->\n\t\t<div class=\"cdx-tabs\">\n\t\t\t<!-- Header with tab buttons -->\n\t\t\t<form class=\"cdx-tabs__header\">\n\t\t\t\t<!-- List of tabs. -->\n\t\t\t\t<div\n\t\t\t\t\tclass=\"cdx-tabs__list\"\n\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\trole=\"tablist\">\n\t\t\t\t\t<!-- Tab list item. -->\n\t\t\t\t\t<button\n\t\t\t\t\t\tid=\"form-tabs-1-label\"\n\t\t\t\t\t\tclass=\"cdx-tabs__list__item\"\n\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\taria-selected=\"true\"\n\t\t\t\t\t\taria-controls=\"form-tabs-1\"\n\t\t\t\t\t\tvalue=\"form-tabs-1\"\n\t\t\t\t\t\tname=\"tab\"\n\t\t\t\t\t\t@click=\"handleTabButtonClick\">\n\t\t\t\t\t\t{{ $i18n( \"donorportal-annual-fund\" ).text() }}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\tid=\"form-tabs-2-label\"\n\t\t\t\t\t\tclass=\"cdx-tabs__list__item\"\n\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\taria-selected=\"false\"\n\t\t\t\t\t\taria-controls=\"form-tabs-2\"\n\t\t\t\t\t\tvalue=\"form-tabs-2\"\n\t\t\t\t\t\tname=\"tab\"\n\t\t\t\t\t\t@click=\"handleTabButtonClick\">\n\t\t\t\t\t\t{{ $i18n( \"donorportal-endowment\" ).text() }}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"dp-table__actions\">\n\t\t\t\t\t<!--button class=\"cdx-button cdx-button--weight-quiet cdx-button--size-medium\">\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\tclass=\"cdx-icon\"\n\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\t\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t\t<g>\n\t\t\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t\t\td=\"M5 1h10v4H5zM3 6a2 2 0 00-2 2v7h4v4h10v-4h4V8a2 2 0 00-2-2zm11 12H6v-6h8zm2-8a1 1 0 111-1 1 1 0 01-1 1\" />\n\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t{{ $i18n( \"donorportal-print-donations\" ).text() }}\n\t\t\t\t\t</button-->\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t\t<!-- Tabs -->\n\t\t\t<div class=\"cdx-tabs__content\">\n\t\t\t\t<!-- <section> element for each tab, with any content inside. -->\n\t\t\t\t<section\n\t\t\t\t\tid=\"form-tabs-1\"\n\t\t\t\t\taria-hidden=\"false\"\n\t\t\t\t\taria-labelledby=\"form-tabs-1-label\"\n\t\t\t\t\tclass=\"cdx-tab\"\n\t\t\t\t\trole=\"tabpanel\"\n\t\t\t\t\ttabindex=\"-1\">\n\t\t\t\t\t<donations-table :donations-list=\"annualFundDonations\"></donations-table>\n\t\t\t\t</section>\n\t\t\t\t<section\n\t\t\t\t\tid=\"form-tabs-2\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\taria-labelledby=\"form-tabs-2-label\"\n\t\t\t\t\tclass=\"cdx-tab\"\n\t\t\t\t\trole=\"tabpanel\"\n\t\t\t\t\ttabindex=\"-1\">\n\t\t\t\t\t<donations-table\n\t\t\t\t\t\tv-if=\"endowmentDonations.length !== 0\"\n\t\t\t\t\t\t:donations-list=\"endowmentDonations\"></donations-table>\n\t\t\t\t\t<endowment-information v-else></endowment-information>\n\t\t\t\t</section>\n\t\t\t</div>\n\t\t\t<!-- End of Tabs -->\n\t\t</div>\n\t</section>\n\t<!-- End of Donation History -->\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst DonationsTable = require( './DonationsListTable.vue' );\nconst EndowmentInformationComponent = require( './EndowmentInformationComponent.vue' );\n\nmodule.exports = exports = defineComponent( {\n\tcomponents: {\n\t\t'donations-table': DonationsTable,\n\t\t'endowment-information': EndowmentInformationComponent\n\t},\n\tprops: {\n\t\tannualFundDonations: {\n\t\t\ttype: Array,\n\t\t\trequired: true,\n\t\t\tdefault() {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t\tendowmentDonations: {\n\t\t\ttype: Array,\n\t\t\trequired: true,\n\t\t\tdefault() {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t}\n\t},\n\tmethods: {\n\t\thandleTabButtonClick: function ( event ) {\n\t\t\tconst tabButtons = document.querySelectorAll( '.cdx-tabs__list__item' );\n\t\t\tconst tabPanels = document.querySelectorAll( '.cdx-tab' );\n\t\t\tevent.preventDefault();\n\n\t\t\t// Deselect all tabs\n\t\t\ttabButtons.forEach( ( btn ) => {\n\t\t\t\tbtn.setAttribute( 'aria-selected', 'false' );\n\t\t\t} );\n\n\t\t\t// Hide all panels\n\t\t\ttabPanels.forEach( ( panel ) => {\n\t\t\t\tpanel.setAttribute( 'aria-hidden', 'true' );\n\t\t\t} );\n\n\t\t\t// Select the clicked tab\n\t\t\tconst selectedTab = event.currentTarget;\n\t\t\tselectedTab.setAttribute( 'aria-selected', 'true' );\n\n\t\t\t// Show the corresponding panel\n\t\t\tconst panelId = selectedTab.getAttribute( 'aria-controls' );\n\t\t\tconst panel = document.getElementById( panelId );\n\t\t\tpanel.setAttribute( 'aria-hidden', 'false' );\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsListTable.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":21,"column":22,"nodeType":"VAttribute","messageId":"unexpected","endLine":21,"endColumn":120},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":41,"column":37,"nodeType":"VAttribute","messageId":"unexpected","endLine":41,"endColumn":60}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<table id=\"donorportal-donations-table\" class=\"dp-table\">\n\t\t<thead>\n\t\t\t<tr>\n\t\t\t\t<th>{{ $i18n( \"donorportal-donation-date\" ).text() }}</th>\n\t\t\t\t<th>{{ $i18n( \"donorportal-donation-type\" ).text() }}</th>\n\t\t\t\t<th class=\"amount\">\n\t\t\t\t\t{{ $i18n( \"donorportal-donation-amount\" ).text() }}\n\t\t\t\t</th>\n\t\t\t\t<th></th>\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody v-if=\"donationsList.length > 0\">\n\t\t\t<tr\n\t\t\t\tv-for=\"donation in currentItems\"\n\t\t\t\t:key=\"donation.id\"\n\t\t\t\tclass=\"donorportal-donations-table-row\">\n\t\t\t\t<td class=\"date\">\n\t\t\t\t\t{{ donation.receive_date_formatted }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"type\" v-html=\"translateDonationTypeStrings( donation.donation_type_key, donation.recurring_status_key )\">\n\t\t\t\t</td>\n\t\t\t\t<td class=\"amount\">\n\t\t\t\t\t<div v-if=\"donation && donation.refunded_status_key\" class=\"status\">\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t{{ refundedStatusLocale( donation.refunded_status_key ) }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<p class=\"amount-currency\">\n\t\t\t\t\t\t{{ donation.amount_formatted }} {{ donation.currency }}\n\t\t\t\t\t</p>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"method\">\n\t\t\t\t\t{{ donation.payment_method }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t</tbody>\n\t</table>\n\t<div class=\"dp-table__footer table-pagination\">\n\t\t<div class=\"pagination__description\">\n\t\t\t<p class=\"text text--body-small\" v-html=\"paginationText\">\n\t\t\t</p>\n\t\t</div>\n\t\t<div class=\"pagination__nav\">\n\t\t\t<button\n\t\t\t\t:disabled=\"currentPage === 1\"\n\t\t\t\tclass=\"cdx-button cdx-button--weight-quiet cdx-button--size-medium pagination-button-first\"\n\t\t\t\t@click=\"setPage( 1 )\">\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"cdx-icon\"\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\t\t\t\t\twidth=\"20\"\n\t\t\t\t\theight=\"20\"\n\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\taria-hidden=\"true\"><g><path d=\"M3 1h2v18H3zm13.5 1.5L15 1l-9 9 9 9 1.5-1.5L9 10z\" /></g></svg>\n\t\t\t</button>\n\t\t\t<button\n\t\t\t\t:disabled=\"currentPage === 1\"\n\t\t\t\tclass=\"cdx-button cdx-button--weight-quiet cdx-button--size-medium pagination-button-prev\"\n\t\t\t\t@click=\"setPage( currentPage - 1 )\">\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"cdx-icon\"\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\t\t\t\t\twidth=\"20\"\n\t\t\t\t\theight=\"20\"\n\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\taria-hidden=\"true\"><g><path d=\"m4 10 9 9 1.4-1.5L7 10l7.4-7.5L13 1z\" /></g></svg>\n\t\t\t</button>\n\t\t\t<div class=\"pagination__nav-pages\">\n\t\t\t\t<div class=\"text text--body-small\">\n\t\t\t\t\tPage\n\t\t\t\t</div>\n\t\t\t\t<select\n\t\t\t\t\tclass=\"cdx-select page-select\"\n\t\t\t\t\t:value=\"currentPage\"\n\t\t\t\t\t@change=\"$e => setPage( $e.target.value )\">\n\t\t\t\t\t<option\n\t\t\t\t\t\tv-for=\"num in numPages\"\n\t\t\t\t\t\t:key=\"`paginationID-${num}`\"\n\t\t\t\t\t\tclass=\"page-select-option\"\n\t\t\t\t\t\t:value=\"num\">\n\t\t\t\t\t\t{{ num }}\n\t\t\t\t\t</option>\n\t\t\t\t</select>\n\t\t\t\t<div class=\"text text--body-small\">\n\t\t\t\t\tof&nbsp; {{ numPages }}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<button\n\t\t\t\t:disabled=\"isLastPage\"\n\t\t\t\tclass=\"cdx-button cdx-button--weight-quiet cdx-button--size-medium pagination-button-next\"\n\t\t\t\t@click=\"setPage( currentPage + 1 )\">\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"cdx-icon\"\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\t\t\t\t\twidth=\"20\"\n\t\t\t\t\theight=\"20\"\n\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\taria-hidden=\"true\"><g><path d=\"M7 1 5.6 2.5 13 10l-7.4 7.5L7 19l9-9z\" /></g></svg>\n\t\t\t</button>\n\t\t\t<button\n\t\t\t\t:disabled=\"isLastPage\"\n\t\t\t\tclass=\"cdx-button cdx-button--weight-quiet cdx-button--size-medium pagination-button-last\"\n\t\t\t\t@click=\"setPage( numPages )\">\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"cdx-icon\"\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\t\t\t\t\twidth=\"20\"\n\t\t\t\t\theight=\"20\"\n\t\t\t\t\tviewBox=\"0 0 20 20\"\n\t\t\t\t\taria-hidden=\"true\"><g><path d=\"M15 1h2v18h-2zM3.5 2.5 11 10l-7.5 7.5L5 19l9-9-9-9z\" /></g></svg>\n\t\t\t</button>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nconst { ref, defineComponent } = require( 'vue' );\nconst pageSize = 10;\nmodule.exports = exports = defineComponent( {\n\tprops: {\n\t\tdonationsList: {\n\t\t\ttype: Array,\n\t\t\trequired: true\n\t\t}\n\t},\n\tsetup( props ) {\n\t\tconst currentPage = ref( 1 );\n\t\treturn {\n\t\t\tcurrentPage,\n\t\t\tnumPages: Math.ceil( props.donationsList.length / pageSize ),\n\t\t\tsetPage: function ( num ) {\n\t\t\t\tthis.currentPage = num;\n\t\t\t},\n\t\t\ttranslateDonationTypeStrings: function ( frequency_key, recurring_status_key ) {\n\t\t\t\tif ( !frequency_key ) {\n\t\t\t\t\treturn 'N/A';\n\t\t\t\t}\n\t\t\t\t// Frequency keys that can be used here\n\t\t\t\t// * donorportal-donation-type-monthly\n\t\t\t\t// * donorportal-donation-type-annual\n\t\t\t\t// * donorportal-donation-type-one-time\n\t\t\t\tlet localeString = this.$i18n( frequency_key ).text();\n\t\t\t\tif ( recurring_status_key ) {\n\t\t\t\t\t// Status keys that can be used here\n\t\t\t\t\t// * donorportal-donation-type-recurring-template\n\t\t\t\t\t// * donorportal-donation-type-inactive-recurring-template\n\t\t\t\t\tlocaleString = this.$i18n(\n\t\t\t\t\t\trecurring_status_key, `<span class=\\\"tag is-recurring\\\">${ localeString }</span>`\n\t\t\t\t\t).text();\n\t\t\t\t}\n\t\t\t\treturn localeString;\n\t\t\t},\n\t\t\trefundedStatusLocale: function ( refunded_status_key ) {\n\t\t\t\tif ( !refunded_status_key ) {\n\t\t\t\t\treturn '';\n\t\t\t\t}\n\t\t\t\t// Refunded status keys that can be used here\n\t\t\t\t// * donorportal-donation-status-refunded\n\t\t\t\treturn this.$i18n( refunded_status_key ).text();\n\t\t}\n\t\t};\n\t},\n\tcomputed: {\n\t\tcurrentItems: function () {\n\t\t\treturn this.donationsList.slice( ( this.currentPage - 1 ) * pageSize, this.currentPage * pageSize );\n\t\t},\n\t\tpaginationText: function () {\n\t\t\tconst start = ( this.currentPage - 1 ) * pageSize + 1;\n\t\t\tlet end = start + ( pageSize - 1 );\n\t\t\tif ( this.isLastPage ) {\n\t\t\t\tend = start + ( this.donationsList.length - ( ( this.currentPage - 1 ) *  pageSize ) ) - 1;\n\t\t\t}\n\t\t\treturn this.$i18n( 'donorportal-donationtable-pagination-text',`<strong>${ start }</strong>`, `<strong>${ end }</strong>`, `<strong>${ this.donationsList.length }</strong>` ).text();\n\t\t},\n\t\tisLastPage: function () {\n\t\t\treturn Number( this.currentPage ) === Number( this.numPages );\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/DonorCardComponent.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/DonorContactDetails.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/EndowmentInformationComponent.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/ErrorComponent.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/FeedbackSurveyComponent.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/GreetingComponent.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/Header.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/OnetimeContribution.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/PopupLink.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RadioButtonInput.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionForm.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":35,"column":37,"nodeType":"VAttribute","messageId":"unexpected","endLine":35,"endColumn":68},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":55,"column":37,"nodeType":"VAttribute","messageId":"unexpected","endLine":55,"endColumn":78},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":100,"column":34,"nodeType":"VAttribute","messageId":"unexpected","endLine":100,"endColumn":63}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<main id=\"form-convert-yearly\" class=\"container\">\n\t\t<section class=\"column--base\">\n\t\t\t<h1 class=\"heading heading--h1\">\n\t\t\t\t{{ $i18n( \"donorportal-update-recurring-annual-convert-head\" ).text() }}\n\t\t\t</h1>\n\t\t\t<p class=\"text text--body\">\n\t\t\t\t{{ $i18n( \"donorportal-update-recurring-annual-convert-description\" ).text() }}\n\t\t\t</p>\n\t\t</section>\n\t\t<form\n\t\t\tclass=\"form\"\n\t\t\t@submit.prevent>\n\t\t\t<section class=\"column--base\">\n\t\t\t\t<p class=\"text text--body\">\n\t\t\t\t\t{{ $i18n( \"donorportal-update-recurring-annual-convert-select-below\" ).text() }}\n\t\t\t\t</p>\n\t\t\t</section>\n\t\t\t<section class=\"column--full speedbump\">\n\t\t\t\t<label for=\"conversion-yearly-upgrade\" class=\"box box--clickable is-recurring\">\n\t\t\t\t\t<div class=\"box__inner\">\n\t\t\t\t\t\t<div class=\"cdx-radio\">\n\t\t\t\t\t\t\t<div class=\"cdx-radio__wrapper\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid=\"conversion-yearly-upgrade\"\n\t\t\t\t\t\t\t\t\tclass=\"cdx-radio__input\"\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tname=\"conversion-yearly\"\n\t\t\t\t\t\t\t\t\t:value=\"yearlyAmount\"\n\t\t\t\t\t\t\t\t\t@click=\"selectYearlyAmountOption\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span class=\"cdx-radio__icon\"></span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<span class=\"text text--body\" v-html=\"convertMonthlyToYearly\">\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t</label>\n\n\t\t\t\t<label for=\"conversion-yearly-current\" class=\"box box--clickable is-recurring\">\n\t\t\t\t\t<div class=\"box__inner\">\n\t\t\t\t\t\t<div class=\"cdx-radio\">\n\t\t\t\t\t\t\t<div class=\"cdx-radio__wrapper\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid=\"conversion-yearly-current\"\n\t\t\t\t\t\t\t\t\tclass=\"cdx-radio__input\"\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tname=\"conversion-yearly\"\n\t\t\t\t\t\t\t\t\t:value=\"recurringContribution.amount\"\n\t\t\t\t\t\t\t\t\t@click=\"selectYearlyAmountOption\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span class=\"cdx-radio__icon\"></span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<span class=\"text text--body\" v-html=\"convertMonthlySameAmountToYearly\">\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t</label>\n\n\t\t\t\t<label for=\"conversion-yearly-other\" class=\"box box--clickable is-recurring\">\n\t\t\t\t\t<div class=\"box__inner\">\n\t\t\t\t\t\t<div class=\"cdx-radio\">\n\t\t\t\t\t\t\t<div class=\"cdx-radio__wrapper\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid=\"conversion-yearly-other\"\n\t\t\t\t\t\t\t\t\tclass=\"cdx-radio__input\"\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tname=\"conversion-yearly\"\n\t\t\t\t\t\t\t\t\t:value=\"otherAmount\"\n\t\t\t\t\t\t\t\t\t@click=\"selectYearlyAmountOption\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span class=\"cdx-radio__icon\"></span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<span class=\"text text--body\">\n\t\t\t\t\t\t\t{{ $i18n( \"donorportal-update-recurring-annual-convert-yearly-other-amount\" ).text() }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<div class=\"dp-input-group\">\n\t\t\t\t\t\t\t<div class=\"cdx-text-input\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tid=\"new-annual-recurring-amount\"\n\t\t\t\t\t\t\t\t\tv-model=\"otherAmount\"\n\t\t\t\t\t\t\t\t\tclass=\"cdx-text-input__input\"\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t:min=\"minAmount\"\n\t\t\t\t\t\t\t\t\t:max=\"maxAmount\"\n\t\t\t\t\t\t\t\t\t@input=\"onInput\"\n\t\t\t\t\t\t\t\t\t@keyup.enter=\"annualConversionAction\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</label>\n\t\t\t</section>\n\t\t\t<section class=\"column--full\">\n\t\t\t\t<ul class=\"checklist\">\n\t\t\t\t\t<li class=\"text text--body\">\n\t\t\t\t\t\t{{ recurringContribution.payment_method }}\n\t\t\t\t\t</li>\n\t\t\t\t\t<li class=\"text text--body\" v-html=\"yearlyConversionDate\">\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</section>\n\t\t</form>\n\n\t\t<section class=\"column--full column--items-center is-recurring\">\n\t\t\t<button\n\t\t\t\tid=\"submit-annual-conversion\"\n\t\t\t\ttype=\"button\"\n\t\t\t\tname=\"submit\"\n\t\t\t\tclass=\"cdx-button cdx-button--weight-primary cdx-button--size-large cdx-button--action-progressive\"\n\t\t\t\t@click=\"annualConversionAction\"\n\t\t\t>\n\t\t\t\t{{ confirmContributionUpdate }}\n\t\t\t</button>\n\t\t</section>\n\n\t\t<section class=\"column--full\">\n\t\t\t<p class=\"text text--body text--align-center\">\n\t\t\t\t{{ $i18n( \"donorportal-cancel-recurring-quit-header\" ).text() }} <router-link\n\t\t\t\t\tid=\"buttonBackToAccount\"\n\t\t\t\t\tto=\"/\"\n\t\t\t\t\tclass=\"link\">\n\t\t\t\t\t{{ $i18n( \"donorportal-return-to-account-button\" ).text() }}\n\t\t\t\t</router-link>\n\t\t\t</p>\n\t\t</section>\n\t</main>\n</template>\n\n<script>\nconst { defineComponent, ref } = require( 'vue' );\nconst { RouterLink } = require( 'vue-router' );\nconst normalizeInput = require( '../normalizeInput.js' );\n\nmodule.exports = exports = defineComponent( {\n\tname: 'RecurringAnnualConversionForm',\n\tcomponents: {\n\t\t'router-link': RouterLink\n\t},\n\tprops: {\n\t\trecurringContribution: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t\tdefaultValue() {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\tsubmitAnnualConversion: {\n\t\t\ttype: Function,\n\t\t\trequired: true\n\t\t},\n\t\tcurrencyRateArray: {\n\t\t\ttype: Array,\n\t\t\trequired: true\n\t\t},\n\t\tmax: {\n\t\t\ttype: Number,\n\t\t\trequired: true\n\t\t}\n\t},\n\temits: [ 'update:modelValue' ],\n\tsetup( props, { emit } ) {\n\t\tconst otherAmount = ref( '' );\n\t\tconst updateAmount = ref( '' );\n\t\tconst priceRange = normalizeInput.getRecurringPriceRange(\n\t\t\tprops.recurringContribution, props.currencyRateArray, props.max\n\t\t);\n\t\tconst minAmount = priceRange[ 0 ];\n\t\tconst maxAmount = priceRange[ 1 ];\n\t\tconst onInput = ( e ) => {\n\t\t\tconst cleaned = normalizeInput.sanitize( e.target.value );\n\t\t\totherAmount.value = cleaned;\n\t\t\t// Auto-select the \"other amount\" radio button\n\t\t\tconst otherRadio = document.getElementById( 'conversion-yearly-other' );\n\t\t\tif ( otherRadio ) {\n\t\t\t\totherRadio.checked = true;\n\t\t\t}\n\t\t\tselectYearlyAmountOption( { target: { value: cleaned } } );\n\t\t\temit( 'update:modelValue', cleaned );\n\t\t};\n\t\tconst selectYearlyAmountOption = ( e ) => {\n\t\t\tupdateAmount.value = e.target.value;\n\t\t};\n\t\tconst annualConversionAction = ( e ) => {\n\t\t\tconst n = parseFloat( updateAmount.value );\n\t\t\tif ( !n || n < minAmount || n > maxAmount ) {\n\t\t\t\talert( 'Please enter a valid amount between ' + minAmount + ' and ' + maxAmount + '.' );\n\t\t\t} else {\n\t\t\t\te.preventDefault();\n\t\t\t\tprops.submitAnnualConversion( updateAmount.value );\n\t\t\t}\n\t\t};\n\t\treturn {\n\t\t\tupdateAmount,\n\t\t\totherAmount,\n\t\t\tonInput,\n\t\t\tannualConversionAction,\n\t\t\tselectYearlyAmountOption,\n\t\t\tminAmount,\n\t\t\tmaxAmount\n\t\t};\n\t},\n\tcomputed: {\n\t\tconfirmContributionUpdate() {\n\t\t\tconst updatedAmount = this.recurringContribution.currency_symbol + this.updateAmount + ' ' + this.recurringContribution.currency;\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-annual-confirm', updatedAmount ).text();\n\t\t},\n\t\tyearlyAmount() {\n\t\t\treturn ( this.recurringContribution.amount * 12 ).toFixed( 2 );\n\t\t},\n\t\tconvertMonthlyToYearly() {\n\t\t\tconst annualAmount = this.yearlyAmount;\n\t\t\tconst formatedAmount = this.recurringContribution.currency_symbol + annualAmount + ' ' + this.recurringContribution.currency;\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-monthly-to-annual-amount',\n\t\t\t\t`<b>${ formatedAmount }</b>` ).text();\n\t\t},\n\t\tconvertMonthlySameAmountToYearly() {\n\t\t\tconst amount = this.recurringContribution.amount_formatted + ' ' + this.recurringContribution.currency;\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-annual-convert-yearly', `<b>${ amount }</b>` ).text();\n\t\t},\n\t\tyearlyConversionDate() {\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-annual-convert-yearly-confirm-next-schedule', `<b>${ this.recurringContribution.next_contribution_date_yearly_formatted }</b>` ).text();\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionSuccess.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":13,"column":33,"nodeType":"VAttribute","messageId":"unexpected","endLine":13,"endColumn":67},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":15,"column":33,"nodeType":"VAttribute","messageId":"unexpected","endLine":15,"endColumn":69}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<main id=\"recurring-contribution-annual-conversion-success\" class=\"container column--items-center\">\n\t\t<section class=\"column--callout\">\n\t\t\t<h1 class=\"heading heading--h1\">\n\t\t\t\t{{ $i18n( \"donorportal-thank-you\" ).text() }}\n\t\t\t</h1>\n\t\t\t<img\n\t\t\t\t:src=\"`${ assets_path }/images/wp_symbols_community.svg`\"\n\t\t\t\talt=\"Community Icon\">\n\t\t</section>\n\t\t<section class=\"column--base\">\n\t\t\t<ul class=\"checklist\">\n\t\t\t\t<li class=\"text text--body\" v-html=\"conversionSuccessToYearly\">\n\t\t\t\t</li>\n\t\t\t\t<li class=\"text text--body\" v-html=\"conversionSuccessOnSchedule\">\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</section>\n\t\t<section class=\"column--base\">\n\t\t\t<router-link\n\t\t\t\tid=\"buttonBackToAccount\"\n\t\t\t\tto=\"/\"\n\t\t\t\tclass=\"cdx-button cdx-button--fake-button cdx-button--fake-button--enabled  cdx-button--weight-primary cdx-button--size-large\"\n\t\t\t>\n\t\t\t\t{{ $i18n( \"donorportal-return-to-account-button\" ).text() }}\n\t\t\t</router-link>\n\t\t</section>\n\t</main>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst { RouterLink } = require( 'vue-router' );\n\nmodule.exports = exports = defineComponent( {\n\tname: 'RecurringContributionAnnualConversionSuccess',\n\tcomponents: {\n\t\t'router-link': RouterLink\n\t},\n\tprops: {\n\t\tnextYearlySchedContributionDateFormatted: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t\tdefaultValue() {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t}\n\t},\n\tsetup() {\n\t\tconst assets_path = mw.config.get( 'assets_path' );\n\n\t\treturn {\n\t\t\tassets_path\n\t\t};\n\t},\n\tcomputed: {\n\t\tconversionSuccessToYearly() {\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-yearly-conversion-success' ).text();\n\t\t},\n\t\tconversionSuccessOnSchedule() {\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-yearly-conversion-on-schedule', `<strong>${ this.nextYearlySchedContributionDateFormatted }</strong>` ).text();\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelAltOptionContainer.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelConfirmation.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelForm.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelSuccess.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":13,"column":33,"nodeType":"VAttribute","messageId":"unexpected","endLine":13,"endColumn":58}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<main id=\"recurring-contribution-cancel-success\" class=\"container column--items-center\">\n\t\t<section class=\"column--callout\">\n\t\t\t<h1 class=\"heading heading--h1\">\n\t\t\t\t{{ $i18n( \"donorportal-cancel-recurring-confirmation-header\" ).text() }}\n\t\t\t</h1>\n\t\t\t<img\n\t\t\t\t:src=\"`${ assets_path }/images/wp_symbols_community.svg`\"\n\t\t\t\talt=\"Community Icon\">\n\t\t</section>\n\t\t<section class=\"column--base\">\n\t\t\t<ul class=\"checklist\">\n\t\t\t\t<li class=\"text text--body\" v-html=\"confirmationText\">\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</section>\n\n\t\t<section class=\"column--base\">\n\t\t\t<a\n\t\t\t\tid=\"shareFeedback\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\t:href=\"surveyUrl\"\n\t\t\t\tclass=\"cdx-button cdx-button--fake-button cdx-button--fake-button--enabled  cdx-button--weight-primary cdx-button--size-large\">\n\t\t\t\t{{ $i18n( \"donorportal-feedback-button\" ).text() }}\n\t\t\t</a>\n\t\t</section>\n\n\t\t<section class=\"column--base\">\n\t\t\t<p class=\"text text--body text--align-center\">\n\t\t\t\t<router-link\n\t\t\t\t\tid=\"buttonBackToAccount\"\n\t\t\t\t\tto=\"/\"\n\t\t\t\t\tclass=\"link\"\n\t\t\t\t>\n\t\t\t\t\t{{ $i18n( \"donorportal-return-to-account-button\" ).text() }}\n\t\t\t\t</router-link>\n\t\t\t</p>\n\t\t</section>\n\t</main>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst { RouterLink } = require( 'vue-router' );\nmodule.exports = exports = defineComponent( {\n\tname: 'RecurringContributionCancelSuccess',\n\tcomponents: {\n\t\t'router-link': RouterLink\n\t},\n\tprops: {\n\t\trecurringContribution: {\n\t\t\ttype: Object,\n\t\t\trequired: true\n\t\t}\n\t},\n\tsetup() {\n\t\tconst assets_path = mw.config.get( 'assets_path' );\n\n\t\treturn {\n\t\t\tassets_path,\n\t\t\tsurveyUrl: mw.config.get( 'surveyUrl' )\n\t\t};\n\t},\n\tcomputed: {\n\t\tamountFormated() {\n\t\t\tif ( !this.recurringContribution ) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\t// Frequency keys that can be used here\n\t\t\t// * donorportal-recurring-amount-annual\n\t\t\t// * donorportal-recurring-amount-monthly\n\t\t\treturn this.$i18n( this.recurringContribution.amount_frequency_key, this.recurringContribution.amount_formatted, this.recurringContribution.currency ).text();\n\t\t},\n\t\tconfirmationText() {\n\t\t\treturn this.$i18n( 'donorportal-cancel-monthly-recurring-confirmation-text', `<strong>${ this.amountFormated }</strong>` ).text();\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":33,"column":29,"nodeType":"VAttribute","messageId":"unexpected","endLine":33,"endColumn":51}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<div :class=\"cardClass\">\n\t\t<div class=\"dp-card__section dp-card__status\">\n\t\t\t<div class=\"dp-card__section dp-card__status\">\n\t\t\t\t<span v-if=\"isCurrentlyActive\" class=\"tag is-recurring\">{{ statusWord }}</span>\n\t\t\t\t<span v-else-if=\"isProcessing\" class=\"tag is-processing\">{{ $i18n( \"donorportal-processing\" ).text() }}</span>\n\t\t\t\t<span v-else class=\"tag\">{{ statusWord }}</span>\n\t\t\t</div>\n\t\t\t<div class=\"dp-card__section dp-card__summary\">\n\t\t\t\t<p class=\"text heading--h2\">\n\t\t\t\t\t<strong v-if=\"isActive || !contribution.hasLastContribution\">{{ contributionAmount }}</strong>\n\t\t\t\t\t<strong v-if=\"!isActive\">{{ $i18n( \"donorportal-renew-support\" ).text() }}</strong>\n\t\t\t\t</p>\n\t\t\t\t<router-link\n\t\t\t\t\tv-if=\"isManageableRecurring\"\n\t\t\t\t\t:to=\"`/manage-donations/${contribution.id}`\"\n\t\t\t\t\tclass=\"cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--action-progressive cdx-button--weight-primary cdx-button--size-large\">\n\t\t\t\t\t{{ $i18n( \"donorportal-manage-donation\" ).text() }}\n\t\t\t\t</router-link>\n\t\t\t</div>\n\n\t\t\t<p v-if=\"isActive\" class=\"text text--body\">\n\t\t\t\t{{ contribution.payment_method }}\n\t\t\t\t[&nbsp;\n\t\t\t\t<popup-link>\n\t\t\t\t\t<template #link-text>\n\t\t\t\t\t\t{{ $i18n( 'donorportal-edit-text' ).text() }}\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #popup-body>\n\t\t\t\t\t\t<h2 id=\"popup-title\">\n\t\t\t\t\t\t\t{{ $i18n( 'donorportal-coming-soon' ).text() }}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t<p class=\"popup-body\" v-html=\"emailTemplate\"></p>\n\t\t\t\t\t</template>\n\t\t\t\t</popup-link>\n\t\t\t\t&nbsp;]\n\t\t\t</p>\n\t\t\t<p v-if=\"isActive\" class=\"text text--body\">\n\t\t\t\t{{ recurringNextContributionAmountWithDate }}\n\t\t\t</p>\n\t\t\t<p v-else-if=\"contribution.hasLastContribution\" class=\"text text--body\">\n\t\t\t\t{{ recurringLastContributionAmountWithDate }}\n\t\t\t</p>\n\t\t</div>\n\t\t<div class=\"dp-card__section dp-card__cta\">\n\t\t\t<a\n\t\t\t\tv-if=\"actionButtonText\"\n\t\t\t\t:target=\"isActive && contribution.can_modify ? '_self' : '_blank'\"\n\t\t\t\t:href=\"isActive && contribution.can_modify ? ( '#/update-donations/' + contribution.id ) : newDonationUrlWithParams\"\n\t\t\t\tclass=\"cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--action-progressive cdx-button--weight-primary cdx-button--size-large\">\n\t\t\t\t{{ actionButtonText }}\n\t\t\t</a>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst PopupLink = require( './PopupLink.vue' );\nconst normalizeInput = require( '../normalizeInput.js' );\nconst { RouterLink } = require( 'vue-router' );\n\nmodule.exports = exports = defineComponent( {\n\tcomponents: {\n\t\t'popup-link': PopupLink,\n\t\t'router-link': RouterLink\n\t},\n\tprops: {\n\t\tcontribution: {\n\t\t\ttype: Object,\n\t\t\trequired: true\n\t\t},\n\t\tisActive: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false\n\t\t}\n\t},\n\tsetup() {\n\t\treturn {\n\t\t\tnewDonationUrl: mw.config.get( 'newDonationUrl' ),\n\t\t\thelpEmail: mw.config.get( 'help_email' ),\n\t\t\tdonorSummary: mw.config.get( 'donorData' )\n\t\t};\n\t},\n\tcomputed: {\n\t\tisPaused: function () {\n\t\t\treturn this.isActive && this.contribution.is_paused;\n\t\t},\n\t\tisProcessing: function () {\n\t\t\treturn this.isActive && this.contribution.is_processing;\n\t\t},\n\t\tisCurrentlyActive: function () {\n\t\t\treturn this.isActive && !this.isPaused && !this.isProcessing;\n\t\t},\n\t\temailTemplate: function () {\n\t\t\tconst here = this.$i18n( 'donorportal-here' );\n\t\t\tconst emailSubject = this.$i18n( 'donorportal-update-payment-method-explanation-template-subject' ).text();\n\t\t\tconst emailBody = this.$i18n( 'donorportal-update-payment-method-explanation-template-body', normalizeInput.escapeHtml( this.donorSummary.name ), this.donorSummary.email, this.contribution.amount_formatted + ' ' + this.contribution.currency ).text();\n\t\t\treturn this.$i18n( 'donorportal-update-payment-method-explanation-template-to', `<a href=\"mailto:${ this.helpEmail }?subject=${ emailSubject }&body=${ emailBody }\">${ here }</a>` ).text();\n\t\t},\n\t\tstatusWord: function () {\n\t\t\tlet keySuffix = 'active';\n\t\t\tif ( !this.isActive ) {\n\t\t\t\tif ( this.contribution.donor_cancelled ) {\n\t\t\t\t\tkeySuffix = 'cancelled';\n\t\t\t\t} else {\n\t\t\t\t\tkeySuffix = 'lapsed';\n\t\t\t\t}\n\t\t\t} else if ( this.isPaused ) {\n\t\t\t\tkeySuffix = 'paused';\n\t\t\t}\n\t\t\t// Messages that can be used here:\n\t\t\t// * donorportal-recurring-status-active\n\t\t\t// * donorportal-recurring-status-lapsed\n\t\t\t// * donorportal-recurring-status-cancelled\n\t\t\t// * donorportal-recurring-status-paused\n\t\t\treturn mw.msg( 'donorportal-recurring-status-' + keySuffix );\n\t\t},\n\t\tcardClass: function () {\n\t\t\tconst base = 'dp-card__appeal';\n\t\t\tif ( this.isActive && !this.isPaused ) {\n\t\t\t\treturn `${ base } is-recurring`;\n\t\t\t}\n\t\t\treturn  `${ base } is-lapsed`;\n\t\t},\n\t\tcontributionAmount: function () {\n\t\t\t// Frequency keys that can be used here\n\t\t\t// * donorportal-recurring-amount-annual\n\t\t\t// * donorportal-recurring-amount-monthly\n\t\t\treturn this.$i18n( this.contribution.amount_frequency_key, this.contribution.amount_formatted, this.contribution.currency ).text();\n\t\t},\n\t\trecurringNextContributionAmountWithDate: function () {\n\t\t\treturn this.$i18n( 'donorportal-recurring-next-amount-and-date', this.contribution.amount_formatted,\n\t\t\t\tthis.contribution.currency, this.contribution.next_sched_contribution_date_formatted ).text();\n\t\t},\n\t\trecurringLastContributionAmountWithDate: function () {\n\t\t\treturn this.$i18n( 'donorportal-last-amount-and-date',\n\t\t\t\tthis.contribution.amount_formatted, this.contribution.currency, this.contribution.last_contribution_date_formatted ).text();\n\t\t},\n\t\tisRecurringModifiable: function () {\n\t\t\treturn this.contribution.can_modify;\n\t\t},\n\t\tisManageableRecurring: function () {\n\t\t\treturn this.isActive && this.isRecurringModifiable && !this.isProcessing;\n\t\t},\n\t\tactionButtonText: function () {\n\t\t\tif ( this.isActive ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Amount frequency keys that can be used here\n\t\t\t// * donorportal-restart-annual\n\t\t\t// * donorportal-restart-monthly\n\t\t\treturn this.$i18n( this.contribution.restart_key ).text();\n\t\t},\n\t\tnewDonationUrlWithParams: function () {\n\t\t\tconst url = new URL( this.newDonationUrl );\n\t\t\turl.searchParams.set( 'preSelect', this.contribution.amount );\n\t\t\turl.searchParams.set( 'country', this.contribution.country  );\n\t\t\turl.searchParams.set( 'frequency', this.contribution.frequency_unit === 'year' ?  'annual' : 'monthly' );\n\t\t\treturn url.toString();\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseForm.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseSuccess.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":13,"column":31,"nodeType":"VAttribute","messageId":"unexpected","endLine":13,"endColumn":60}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<main id=\"recurring-contribution-pause-success\" class=\"greeting container column--items-center\">\n\t\t<section class=\"container__inner dp-dashboard__intro\">\n\t\t\t<router-link\n\t\t\t\tid=\"buttonBackToAccount\"\n\t\t\t\tto=\"/\"\n\t\t\t\tclass=\"text text--body link link--muted link--no-underline\">\n\t\t\t\t← <span class=\"link--underline\">{{ $i18n( \"donorportal-return-to-account-button\" ).text() }}</span>\n\t\t\t</router-link>\n\t\t\t<h1 class=\"heading heading--subtle heading--h2\">\n\t\t\t\t{{ $i18n( \"donorportal-pause-recurring-confirmation-header\" ).text() }}\n\t\t\t</h1>\n\t\t\t<p class=\"text text--body\" v-html=\"nextContributionDate\"></p>\n\t\t</section>\n\t</main>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst { RouterLink } = require( 'vue-router' );\nmodule.exports = exports = defineComponent( {\n\tname: 'RecurringContributionPauseSuccess',\n\tcomponents: {\n\t\t'router-link': RouterLink\n\t},\n\tprops: {\n\t\tnextSchedContributionDate: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t\tdefaultValue() {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t}\n\t},\n\tcomputed: {\n\t\tnextContributionDate() {\n\t\t\treturn this.$i18n( 'donorportal-pause-recurring-confirmation-subheader', `<strong>${ this.nextSchedContributionDate }</strong>` ).text();\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionSummary.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateForm.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateSuccess.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":15,"column":33,"nodeType":"VAttribute","messageId":"unexpected","endLine":15,"endColumn":58}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<main id=\"recurring-contribution-update-success\" class=\"container column--items-center\">\n\t\t<section class=\"column--callout\">\n\t\t\t<h1 class=\"heading heading--h1\">\n\t\t\t\t{{ $i18n( 'donorportal-update-recurring-confirmation-header' ).text() }}\n\t\t\t\t<br>\n\t\t\t\t{{ $i18n( 'donorportal-update-recurring-confirmation-header-subtitle' ).text() }}\n\t\t\t</h1>\n\t\t\t<img\n\t\t\t\t:src=\"`${ assets_path }/images/wp_symbols_community.svg`\"\n\t\t\t\talt=\"Community Icon\">\n\t\t</section>\n\t\t<section class=\"column--base\">\n\t\t\t<ul class=\"checklist\">\n\t\t\t\t<li class=\"text text--body\" v-html=\"confirmationText\">\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t</section>\n\t\t<section class=\"column--base\">\n\t\t\t<router-link\n\t\t\t\tid=\"buttonBackToAccount\"\n\t\t\t\tto=\"/\"\n\t\t\t\tclass=\"cdx-button cdx-button--fake-button cdx-button--fake-button--enabled  cdx-button--weight-primary cdx-button--size-large\"\n\t\t\t>\n\t\t\t\t{{ $i18n( \"donorportal-return-to-account-button\" ).text() }}\n\t\t\t</router-link>\n\t\t</section>\n\t</main>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst { RouterLink } = require( 'vue-router' );\nmodule.exports = exports = defineComponent( {\n\tname: 'RecurringContributionUpdateSuccess',\n\tcomponents: {\n\t\t'router-link': RouterLink\n\t},\n\tprops: {\n    nextSchedContributionDate: {\n\t\t\ttype: String,\n\t\t\trequired: true\n\t\t},\n    newAmount: {\n\t\t\ttype: String,\n\t\t\trequired: true\n\t\t}\n\t},\n\tsetup() {\n\t\tconst assets_path = mw.config.get( 'assets_path' );\n\n\t\treturn {\n\t\t\tassets_path\n\t\t};\n\t},\n\tcomputed: {\n\t\tconfirmationText() {\n\t\t\treturn this.$i18n( 'donorportal-update-recurring-confirmation-text', `<strong>${ this.newAmount }</strong>`, `<strong>${ this.nextSchedContributionDate }</strong>` ).text();\n\t\t}\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/components/RelatedContentComponent.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/init.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/normalizeInput.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/router.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/trackingParams.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/AmountDowngrade.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/AnnualConversion.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/CancelDonations.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/Home.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/LoginView.vue","messages":[{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":8,"column":6,"nodeType":"VAttribute","messageId":"unexpected","endLine":8,"endColumn":30},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":37,"column":7,"nodeType":"VAttribute","messageId":"unexpected","endLine":37,"endColumn":30},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":66,"column":8,"nodeType":"VAttribute","messageId":"unexpected","endLine":66,"endColumn":33},{"ruleId":"vue/no-v-html","severity":1,"message":"'v-html' directive can lead to XSS attack.","line":76,"column":17,"nodeType":"VAttribute","messageId":"unexpected","endLine":76,"endColumn":39}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":"<template>\n\t<main class=\"auth\">\n\t\t<section class=\"auth__infobox\">\n\t\t\t<div v-if=\"server_error\" class=\"auth__infobox-inner\">\n\t\t\t\t<p\n\t\t\t\t\tid=\"server-error-message-text\"\n\t\t\t\t\tclass=\"text text--body-small\"\n\t\t\t\t\tv-html=\"serverErrorText\"></p>\n\t\t\t</div>\n\t\t\t<div v-else class=\"auth__infobox-inner\">\n\t\t\t\t<div class=\"auth__intro\">\n\t\t\t\t\t<h1 class=\"heading heading--h1\">\n\t\t\t\t\t\t{{ $i18n( \"donorportal-login-header\" ).text() }}\n\t\t\t\t\t</h1>\n\t\t\t\t\t<p class=\"text text--body-small\">\n\t\t\t\t\t\t{{ $i18n( \"donorportal-login-text\" ).text() }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<form class=\"auth__form send-new-link\">\n\t\t\t\t\t<div class=\"cdx-text-input\" :class=\"[ { 'cdx-text-input--status-error': api_error === 'invalid_email' || api_error === 'missingparam' } ]\">\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid=\"new-checksum-link-email\"\n\t\t\t\t\t\t\tref=\"new-checksum-link-email\"\n\t\t\t\t\t\t\tclass=\"cdx-text-input__input\"\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t:value=\"donorEmail\"\n\t\t\t\t\t\t\t:placeholder=\"emailPlaceholder\"\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t@input=\"handleInputChange\"\n\t\t\t\t\t\t>\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\tid=\"request-link-button\"\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tclass=\"cdx-button cdx-button--action-progressive cdx-button--weight-primary\"\n\t\t\t\t\t\t@click=\"handleSubmitButtonClick\"\n\t\t\t\t\t\tv-html=\"newLinkRequest\">\n\t\t\t\t\t</button>\n\t\t\t\t</form>\n\t\t\t\t<p\n\t\t\t\t\tid=\"link-sent-text\"\n\t\t\t\t\tclass=\"link-sent\"\n\t\t\t\t\t:style=\"`display: ${checksum_link_sent ? 'block' : 'none'};`\">\n\t\t\t\t\t{{ $i18n( \"emailpreferences-new-link-sent\" ).text() }}\n\t\t\t\t</p>\n\t\t\t\t<p\n\t\t\t\t\tid=\"error-message-text\"\n\t\t\t\t\tclass=\"text--body-small\"\n\t\t\t\t\t:class=\"[ { 'invalid-error-message-text': api_error === 'invalid_email' || api_error === 'InvalidCredentials' || api_error === 'missingparam' } ]\"\n\t\t\t\t\t:style=\"`display: ${error_message ? 'block' : 'none'};`\">\n\t\t\t\t\t{{ error_message }}\n\t\t\t\t</p>\n\t\t\t\t<popup-link v-if=\"!server_error\">\n\t\t\t\t\t<template #link-text>\n\t\t\t\t\t\t{{ $i18n( 'donorportal-login-problems' ).text() }}\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #popup-body>\n\t\t\t\t\t\t<h2 id=\"popup-title\">\n\t\t\t\t\t\t\t{{ $i18n( 'donorportal-login-problems' ).text() }}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t<p class=\"popup-body\">\n\t\t\t\t\t\t\t{{ $i18n( 'donorportal-update-donation-problem-log-in' ).text() }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclass=\"popup-body\"\n\t\t\t\t\t\t\tv-html=\"problemLoginLink\"></p>\n\t\t\t\t\t</template>\n\t\t\t\t</popup-link>\n\t\t\t</div>\n\t\t</section>\n\t\t<section class=\"auth__display\">\n\t\t\t<figure>\n\t\t\t\t<img\n\t\t\t\t\tsrc=\"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Sunrise_View_of_Inle_Lake.jpg/1280px-Sunrise_View_of_Inle_Lake.jpg\"\n\t\t\t\t\t:alt=\"figureAltText\">\n\t\t\t\t<figcaption v-html=\"figureCaption\"></figcaption>\n\t\t\t</figure>\n\t\t</section>\n\t</main>\n</template>\n\n<script>\nconst { defineComponent } = require( 'vue' );\nconst PopupLink = require( '../components/PopupLink.vue' );\nconst { requestNewChecksumLink } = require( '../ApiUtils.js' );\n\nmodule.exports = exports = defineComponent( {\n\tcomponents: {\n\t\t'popup-link': PopupLink\n\t},\n\tsetup() {\n\t\treturn {\n\t\t\thelpEmail: mw.config.get( 'help_email' )\n\t\t};\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tdonorEmail: '',\n\t\t\tapi_error: '',\n\t\t\tchecksum_link_sent: false,\n\t\t\tserver_error: ''\n\t\t};\n\t},\n\tcomputed: {\n\t\tfigureTitle() {\n\t\t\treturn this.$i18n( 'donorportal-loginpage-figure-title' ).text();\n\t\t},\n\t\tnewLinkRequest() {\n\t\t\treturn this.$i18n( 'emailpreferences-send-new-link' ).text();\n\t\t},\n\t\temailPlaceholder() {\n\t\t\treturn this.$i18n( 'donorportal-login-email-placeholder' ).text();\n\t\t},\n\t\tproblemLoginLink() {\n\t\t\tconst donorRelationTeam = this.$i18n( 'donorportal-update-donation-donor-relations-team' ).text();\n\t\t\tconst problemLogin = this.$i18n( 'donorportal-login-problems' ).text();\n\t\t\treturn this.$i18n( 'donorportal-update-donation-problem-log-in-contact-us', `<a href=\"mailto:${ this.helpEmail }?subject=${ problemLogin }\">${ donorRelationTeam }</a>` ).text();\n\t\t},\n\t\tserverErrorText() {\n\t\t\tconst donorRelationTeam = this.$i18n( 'donorportal-update-donation-donor-relations-team' ).text();\n\t\t\tconst problemLogin = this.$i18n( 'donorportal-login-problems-email-subject' ).text();\n\t\t\treturn this.$i18n( 'donorportal-authentication-failure', `<a href=\"mailto:${ this.helpEmail }?subject=${ problemLogin }\">${ donorRelationTeam }</a>` ).text();\n\t\t},\n\t\tfigureCaption() {\n\t\t\treturn this.$i18n( 'donorportal-loginpage-figure-caption', `<a href=\\\"https://commons.wikimedia.org/wiki/File:Sunrise_View_of_Inle_Lake.jpg\\\"\n\t\t\t target=\\\"_blank\\\">${ this.figureTitle }</a>` ).text();\n\t\t},\n\t\tfigureAltText() {\n\t\t\treturn this.$i18n( 'donorportal-loginpage-figure-alt', this.figureTitle ).text();\n\t\t},\n\t\terror_message: function () {\n\t\t\tif ( this.api_error ) {\n\t\t\t\tswitch ( this.api_error ) {\n\t\t\t\t\tcase 'missingparam':\n\t\t\t\t\t\treturn this.$i18n( 'donorportal-email-required' ).text();\n\t\t\t\t\tcase 'Unreachable':\n\t\t\t\t\t\treturn this.$i18n( 'donorportal-civi-unavailable-error-message' ).text();\n\t\t\t\t\tcase 'invalid_email':\n\t\t\t\t\t\treturn this.$i18n( 'donorportal-invalid-email-error-message' ).text();\n\t\t\t\t\tcase 'InvalidCredentials':\n\t\t\t\t\t\treturn this.$i18n( 'donorportal-invalid-credentials-error-message' ).text();\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn this.$i18n( 'donorportal-something-wrong' ).text();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn '';\n\t\t}\n\t},\n\tmethods: {\n\t\tsetServerErrorFromDonorData() {\n\t\t\t/*\n\t\t\t * We should always have a value for donorData\n\t\t\t * If \"null\" is set, something must be wrong.\n\t\t\t */\n\t\t\tconst donorData = mw.config.get( 'donorData' );\n\n\t\t\t// Set server error to true when null data is set in user session\n\t\t\tthis.server_error = !donorData;\n\n\t\t\tif ( donorData && donorData.error ) {\n\t\t\t\t// Set server error for errors that do not include Unreachable civi or invalid checksum\n\t\t\t\tthis.server_error = donorData.error && !donorData.showLogin;\n\n\t\t\t\t// There's an error but user is able to request a login checksum (maybe CiviCRM is down)\n\t\t\t\tif ( donorData.showLogin ) {\n\t\t\t\t\tthis.api_error = donorData.error_code;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\thandleSubmitButtonClick( e ) {\n\t\t\te.preventDefault();\n\t\t\t// Ensure no request is made after first successful request\n\t\t\tif ( this.$refs[ 'new-checksum-link-email' ].disabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.$refs[ 'new-checksum-link-email' ].disabled = true;\n\t\t\trequestNewChecksumLink(\n\t\t\t\tthis.donorEmail,\n\t\t\t\tmw.config.get( 'requestNewChecksumPage' ),\n\t\t\t\tmw.config.get( 'requestNewChecksumSubpage' )\n\t\t\t).then( () => {\n\t\t\t\tthis.checksum_link_sent = true;\n\t\t\t} ).catch( ( error ) => {\n\t\t\t\tthis.api_error = error;\n\t\t\t\tthis.$refs[ 'new-checksum-link-email' ].disabled = false;\n\t\t\t} );\n\t\t},\n\t\thandleInputChange( e ) {\n\t\t\tthis.donorEmail = e.target.value.trim();\n\t\t\tthis.api_error = '';\n\t\t}\n\t},\n\tmounted() {\n\t\tthis.setServerErrorFromDonorData();\n\t}\n} );\n</script>\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/ManageDonations.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/PauseDonations.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/ext.donationInterface.donorPortal/views/UpdateDonations.vue","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"vue/component-tags-order","replacedBy":["block-order"]},{"ruleId":"vue/no-invalid-model-keys","replacedBy":["valid-model-definition"]},{"ruleId":"vue/v-on-function-call","replacedBy":["v-on-handler-style"]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/iframe.liberator.js","messages":[{"ruleId":"no-redeclare","severity":1,"message":"'self' is already defined as a built-in global variable.","line":1,"column":10,"nodeType":"Block","messageId":"redeclaredAsBuiltin","endLine":1,"endColumn":14}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/*global self:false */\n$( () => {\n\t// we're going to immediately redirect.\n\t// Hide the page contents (skin, mostly) so it doesn't appear in the iframe while we're waiting for the reload.\n\tjQuery( 'body' ).children().attr( 'style', 'display:none' );\n} );\ntop.location = self.document.location + '&liberated=1';\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.alwaysRedirect.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.applePayHelper.js","messages":[{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"$\" type.","line":4,"column":1,"nodeType":"Block","endLine":4,"endColumn":1},{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"mw\" type.","line":5,"column":1,"nodeType":"Block","endLine":5,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Apple Pay helper functions for DonationInterface forms\n *\n * @param $ jQuery\n * @param mw mediaWiki\n */\n( function ( $, mw ) {\n\tconst di = mw.donationInterface; // Defined in ext.donationInterface.validation.js\n\tdi.forms = di.forms || {};\n\n\tfunction isNotEmpty( string ) {\n\t\treturn string && string.trim().length > 0;\n\t}\n\n\tfunction isLongerThan1Char( string ) {\n\t\treturn string && string.trim().length > 1;\n\t}\n\n\tfunction hasBothNamesLongerThan1Char( contact ) {\n\t\treturn contact && isLongerThan1Char( contact.givenName ) && isLongerThan1Char( contact.familyName );\n\t}\n\n\tfunction hasBothNames( contact ) {\n\t\treturn contact && isNotEmpty( contact.givenName ) && isNotEmpty( contact.familyName );\n\t}\n\n\tdi.forms.apple = {\n\t\t/*\n\t\t * Try to obtain the \"best\" name from the available contact info sent back by Apple Pay\n\t\t *\n\t\t * @see https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentrequest/2216120-requiredbillingcontactfields\n\t\t * @see https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentcontact\n\t\t */\n\t\tgetBestApplePayContactName: function (\n\t\t\textraData,\n\t\t\tbillingContact,\n\t\t\tshippingContact\n\t\t) {\n\t\t\tlet preferredContact;\n\n\t\t\t// Since the Apple Pay sheet shows the name by the shipping contact selector,\n\t\t\t// we might want to check the shipping contact first, but in practice we were\n\t\t\t// getting a lot of low-quality names (e.g. 'Dad') from the shipping contact.\n\t\t\t// The billing contact seems to more consistently have real names so start there.\n\t\t\tif ( hasBothNamesLongerThan1Char( billingContact ) ) {\n\t\t\t\tpreferredContact = billingContact;\n\t\t\t} else if ( hasBothNamesLongerThan1Char( shippingContact ) ) {\n\t\t\t\tpreferredContact = shippingContact;\n\t\t\t} else if ( hasBothNames( billingContact ) ) {\n\t\t\t\tpreferredContact = billingContact;\n\t\t\t} else if ( hasBothNames( shippingContact ) ) {\n\t\t\t\tpreferredContact = shippingContact;\n\t\t\t}\n\n\t\t\tif ( preferredContact ) {\n\t\t\t\textraData.first_name = preferredContact.givenName.trim();\n\t\t\t\textraData.last_name = preferredContact.familyName.trim();\n\t\t\t}\n\n\t\t\treturn extraData;\n\t\t}\n\t};\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.emailPreferences.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.employerAutoComplete.js","messages":[{"ruleId":"no-jquery/no-done-fail","severity":1,"message":"Prefer .then to .done","line":28,"column":21,"nodeType":"CallExpression","endLine":49,"endColumn":24}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $ ) {\n    $( () => {\n        const autocompleteCache = {},\n            // This triggers both on 'select' and 'focus' events to set the displayed\n            // value to the employer/subsidiary name and the hidden field value to the\n            // employer ID. The focus event is triggered on arrow key navigation.\n            selectFocusFunction = function ( event, ui ) {\n                event.preventDefault();\n                $( '#employer' ).val( ui.item.label );\n                $( '#employer_id' ).val( ui.item.value );\n            };\n\n        $( '#employer' ).autocomplete( {\n            delay: 300, //throttle in milliseconds\n            source: function ( request, response ) {\n                //reset employer_id each time a new search starts\n                $( '#employer_id' ).val( '' );\n\n                const apiParameters = {\n                    action: 'employerSearch',\n                    employer: request.term,\n                    format: 'json'\n                }, cached = autocompleteCache[ request.term ];\n\n                if ( cached ) {\n                    response( cached );\n                } else {\n                    $.post( mw.util.wikiScript( 'api' ), apiParameters ).done( ( data ) => {\n                        // check if the api sent back any errors and if so jump out here\n                        if ( data.error ) {\n                            response(); // this has to be called in all scenarios for preserve the widget state\n                        } else {\n                            // transform result to suit autocomplete format\n                            const result = data.result.map( ( item ) => ( {\n                                        label: item.name,\n                                        value: item.id\n                                    } ) ),\n                            //trim results\n                            output = result.slice( 0, 10 );\n\n                            // Note: jquery autocomplete handles escaping by injecting\n                            // values and labels into the DOM using jquery text() and\n                            // val() methods. So, additional escaping is not needed.\n\n                            //cache result\n                            autocompleteCache[ request.term ] = output;\n                            response( output );\n                        }\n                    } );\n                }\n            },\n            select: selectFocusFunction,\n            focus: selectFocusFunction\n        } );\n    } );\n} )( jQuery );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.employerExplain.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.employerExplainAlt.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.errorLog.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'postdata' is never reassigned. Use 'const' instead.","line":16,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":16,"endColumn":11}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $, mw ) {\n\tconst apiAction = mw.config.get( 'ClientErrorLogAction', 'logPaymentsFormError' ),\n\t\tignorePatterns = mw.config.get( 'wgDonationInterfaceClientErrorLogIgnorePatterns' ),\n\t\tignoreRegexes = [];\n\twindow.onerror = function ( message, file, line, col, error ) {\n\t\tlet i, postdata;\n\t\tfor ( i = 0; i < ignorePatterns.length; i++ ) {\n\t\t\tif ( ignoreRegexes.length <= i ) {\n\t\t\t\t// turn patterns into regexes the first time through\n\t\t\t\tignoreRegexes[ i ] = new RegExp( ignorePatterns[ i ] );\n\t\t\t}\n\t\t\tif ( message.match( ignoreRegexes[ i ] ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tpostdata = {\n\t\t\taction: apiAction,\n\t\t\tmessage: message,\n\t\t\tfile: file,\n\t\t\tline: line,\n\t\t\tcol: col,\n\t\t\tuserAgent: navigator.userAgent\n\t\t};\n\t\tif ( error && error.stack ) {\n\t\t\tpostdata.stack = error.stack;\n\t\t}\n\t\t$.ajax( {\n\t\t\turl: mw.util.wikiScript( 'api' ),\n\t\t\tdata: postdata,\n\t\t\tdataType: 'json',\n\t\t\ttype: 'POST'\n\t\t} );\n\t};\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.forms.js","messages":[{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"$\" type.","line":4,"column":1,"nodeType":"Block","endLine":4,"endColumn":1},{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"mw\" type.","line":5,"column":1,"nodeType":"Block","endLine":5,"endColumn":1},{"ruleId":"no-jquery/no-sizzle","severity":1,"message":"Selector extensions are not allowed","line":74,"column":27,"nodeType":"CallExpression","endLine":74,"endColumn":69},{"ruleId":"prefer-const","severity":1,"message":"'$element' is never reassigned. Use 'const' instead.","line":90,"column":12,"nodeType":"Identifier","messageId":"useConst","endLine":90,"endColumn":20},{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"checkboxName\" type.","line":107,"column":1,"nodeType":"Block","endLine":107,"endColumn":1},{"ruleId":"prefer-const","severity":1,"message":"'$element' is never reassigned. Use 'const' instead.","line":111,"column":12,"nodeType":"Identifier","messageId":"useConst","endLine":111,"endColumn":20},{"ruleId":"jsdoc/no-undefined-types","severity":1,"message":"The type 'result' is undefined.","line":126,"column":1,"nodeType":"Block","endLine":126,"endColumn":1},{"ruleId":"prefer-const","severity":1,"message":"'sendData' is never reassigned. Use 'const' instead.","line":148,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":148,"endColumn":11},{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":187,"column":4,"nodeType":"MemberExpression","messageId":"forbidden","endLine":187,"endColumn":17},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":239,"column":14,"nodeType":"Identifier","messageId":"forbidden","endLine":239,"endColumn":21},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":269,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":269,"endColumn":17},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":283,"column":4,"nodeType":"Identifier","messageId":"forbidden","endLine":283,"endColumn":11},{"ruleId":"no-jquery/no-sizzle","severity":1,"message":"Selector extensions are not allowed","line":321,"column":10,"nodeType":"CallExpression","endLine":321,"endColumn":64},{"ruleId":"no-jquery/no-sizzle","severity":1,"message":"Selector extensions are not allowed","line":325,"column":30,"nodeType":"CallExpression","endLine":325,"endColumn":76}],"suppressedMessages":[{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '<<'.","line":292,"column":13,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":292,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-bitwise","severity":2,"message":"Unexpected use of '>>>'.","line":296,"column":12,"nodeType":"BinaryExpression","messageId":"unexpected","endLine":296,"endColumn":22,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":14,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Core functionality for DonationInterface forms\n *\n * @param $\n * @param mw\n */\n( function ( $, mw ) {\n\tconst di = mw.donationInterface; // Defined in ext.donationInterface.validation.js\n\n\t// Common helper functions\n\tfunction disablePaymentSubmitButton() {\n\t\t$( '#paymentSubmitBtn' ).prop( 'disabled', true );\n\t\t$( '#paymentSubmitBtn' ).removeClass( 'enabled' ).addClass( 'disabled' );\n\t}\n\n\tfunction enablePaymentSubmitButton() {\n\t\t$( '#paymentSubmitBtn' ).prop( 'disabled', false );\n\t\t$( '#paymentSubmitBtn' ).removeClass( 'disabled' ).addClass( 'enabled' );\n\t}\n\n\t/**\n\t * Disable all interaction with the form, including buttons.\n\t * Usually done by drawing a semi-opaque overlay.\n\t */\n\tfunction disableForm() {\n\t\t$( '#overlay' ).show();\n\t\tdisablePaymentSubmitButton();\n\t}\n\n\t/**\n\t * Mark all form input fields disabled. This can be used to indicate that\n\t * no revision to donor info is possible after a card iframe is opened.\n\t */\n\tfunction disableInput() {\n\t\t$( '[type=text], [type=number], [type=email], select' ).each( function () {\n\t\t\t$( this ).attr( 'disabled', true );\n\t\t} );\n\t}\n\n\t/**\n\t * Makes a form disabled with disableForm usable again.\n\t */\n\tfunction enableForm() {\n\t\t$( '#overlay' ).hide();\n\t\tenablePaymentSubmitButton();\n\t}\n\n\t/**\n\t * Re-enable input fields disabled with disableInput.\n\t */\n\tfunction enableInput() {\n\t\t$( '[type=text], [type=number], [type=email] select' ).each( function () {\n\t\t\t$( this ).removeAttr( 'disabled' );\n\t\t} );\n\t}\n\n\t/**\n\t * Submit a basic form.\n\t */\n\tfunction submitForm() {\n\t\tdi.forms.disable();\n\t\tdi.forms.clean();\n\t\t$( '#payment-form' )[ 0 ].submit();\n\t}\n\n\tfunction cleanInput() {\n\t\t// Trim all the trimmable inputs\n\t\t$( '[type=text], [type=number], [type=email]' ).each( function () {\n\t\t\t$( this ).val( $.trim( this.value ) );\n\t\t} );\n\t}\n\n\tfunction resetSubmethod() {\n\t\tconst $submethodInput = $( 'input:radio[name=payment_submethod]' );\n\t\tif ( $submethodInput.length > 1 ) {\n\t\t\t$submethodInput.prop( 'checked', false );\n\t\t}\n\t}\n\n\t/**\n\t * Get a trinary value from a checkbox that may exist, falling back\n\t *  to a querystring value.\n\t *  '0' = checkbox shown and not checked, or 0 on querystring\n\t *  '1' = checkbox shown and checked, or 1 on querystring\n\t *  '' = checkbox not shown, querystring value missing\n\t *\n\t * @return {string}\n\t */\n\tfunction getOptIn() {\n\t\tlet val, $element = $( 'input[name=opt_in]:checked' );\n\t\tif ( $element.length === 1 ) {\n\t\t\tval = $element.val();\n\t\t} else {\n\t\t\tval = mw.util.getParamValue( 'opt_in' );\n\t\t\tif ( val === null ) {\n\t\t\t\tval = '';\n\t\t\t}\n\t\t}\n\t\treturn val;\n\t}\n\n\t/**\n\t * Get a binary value from a checkbox that may exist\n\t *  '0' = checkbox shown and not checked, checkbox not shown\n\t *  '1' = checkbox shown and checked\n\t *\n\t * @param checkboxName\n\t * @return {string}\n\t */\n\tfunction handleCheckbox( checkboxName ) {\n\t\tlet val, $element = $( 'input[name=' + checkboxName + ']:checked' );\n\t\tif ( $element.length === 1 ) {\n\t\t\tval = $element.val();\n\t\t} else {\n\t\t\tval = mw.util.getParamValue( checkboxName );\n\t\t\tif ( val === null ) {\n\t\t\t\tval = 0;\n\t\t\t}\n\t\t}\n\t\treturn val;\n\t}\n\n\t/**\n\t * Call the generic donation API and handle errors or execute a callback\n\t *\n\t * @param {function(result)} successCallback will be called with response's 'result' property\n\t * @param {Array} extraData will be merged into the data collected from the form\n\t * @param {string} action action param to pass to MW API, defaults to 'donate'\n\t */\n\tfunction callDonateApi( successCallback, extraData, action ) {\n\t\tdi.forms.disable();\n\t\tdi.forms.clean();\n\t\t$( '#topError' ).html( '' );\n\t\t$( '#errorReference' )\n\t\t\t.removeClass( 'errorMsg' )\n\t\t\t.addClass( 'errorMsgHide' );\n\t\t$( '#paymentContinueBtn' ).removeClass( 'enabled' );\n\n\t\tlet sendData,\n\t\t\tpaymentSubmethod;\n\n\t\tif ( typeof $( 'input[name=\"payment_submethod\"]:checked' ).val() === 'undefined' ) {\n\t\t\tpaymentSubmethod = '';\n\t\t} else {\n\t\t\tpaymentSubmethod = $( 'input[name=\"payment_submethod\"]:checked' ).val().toLowerCase();\n\t\t}\n\n\t\tsendData = {\n\t\t\taction: action || 'donate',\n\t\t\tbin_hash: $( '#bin_hash' ).val(),\n\t\t\tgateway: $( '#gateway' ).val(),\n\t\t\tchecksum: $( '#checksum' ).val(),\n\t\t\tcontact_id: $( '#contact_id' ).val(),\n\t\t\tcontact_hash: $( '#contact_hash' ).val(),\n\t\t\tcurrency: $( '#currency' ).val(),\n\t\t\tamount: $( '#amount' ).val(),\n\t\t\tfirst_name: $( '#first_name' ).val(),\n\t\t\tlast_name: $( '#last_name' ).val(),\n\t\t\tstreet_address: $( '#street_address' ).val(),\n\t\t\tcity: $( '#city' ).val(),\n\t\t\tstate_province: $( '#state_province' ).val(),\n\t\t\tpostal_code: $( '#postal_code' ).val(),\n\t\t\tphone: $( '#phone' ).val(),\n\t\t\tsms_opt_in: handleCheckbox( 'sms_opt_in' ),\n\t\t\temail: $( '#email' ).val(),\n\t\t\tcountry: $( '#country' ).val(),\n\t\t\tpayment_method: $( '#payment_method' ).val(),\n\t\t\tlanguage: $( '#language' ).val(),\n\t\t\tpayment_submethod: paymentSubmethod,\n\t\t\tprocessor_form: $( '#processor_form' ).val(),\n\t\t\tissuer_id: $( '#issuer_id' ).val(),\n\t\t\tutm_source: $( '#utm_source' ).val(),\n\t\t\tutm_campaign: $( '#utm_campaign' ).val(),\n\t\t\tutm_medium: $( '#utm_medium' ).val(),\n\t\t\treferrer: $( '#referrer' ).val(),\n\t\t\trecurring: $( '#recurring' ).val(),\n\t\t\tvariant: $( '#variant' ).val(),\n\t\t\twmf_token: $( '#wmf_token' ).val(),\n\t\t\topt_in: getOptIn(),\n\t\t\temployer: $( '#employer' ).val(),\n\t\t\temployer_id: $( '#employer_id' ).val(),\n\t\t\tstreet_number: $( '#street_number' ).val(),\n\t\t\tformat: 'json'\n\t\t};\n\n\t\tif ( extraData ) {\n\t\t\tObject.assign( sendData, extraData );\n\t\t}\n\n\t\t// If debug logging is enabled and there are debug messages, send them.\n\t\tif ( mw.config.get( 'wgDonationInterfaceLogDebug' ) &&\n\t\t\tdi.forms.debugMessages.length > 0 ) {\n\t\t\tsendData.debug_messages = di.forms.debugMessages.join( '\\n' );\n\t\t}\n\n\t\t$.ajax( {\n\t\t\turl: mw.util.wikiScript( 'api' ),\n\t\t\tdata: sendData,\n\t\t\tdataType: 'json',\n\t\t\ttype: 'POST',\n\t\t\tsuccess: function ( data ) {\n\t\t\t\tif ( typeof data.error !== 'undefined' ) {\n\t\t\t\t\t// FIXME alert sux\n\t\t\t\t\talert( mw.msg( 'donate_interface-error-msg-general' ) );\n\t\t\t\t\t// Show continue button in 2nd section if it exists\n\t\t\t\t\t$( '#paymentContinue' ).show();\n\t\t\t\t} else if ( typeof data.result !== 'undefined' ) {\n\t\t\t\t\tif ( data.result.errors ) {\n\t\t\t\t\t\tmw.donationInterface.validation.showErrors( data.result.errors );\n\t\t\t\t\t\t// Show continue button in 2nd section if it exists\n\t\t\t\t\t\t$( '#paymentContinue' ).show();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsuccessCallback( data.result );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function ( xhr ) {\n\t\t\t\t// FIXME too\n\t\t\t\talert( mw.msg( 'donate_interface-error-msg-general' ) );\n\t\t\t},\n\t\t\tcomplete: function () {\n\t\t\t\tdi.forms.enable();\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction isIframe() {\n\t\tconst payment_method = $( '#payment_method' ).val();\n\n\t\tswitch ( payment_method ) {\n\t\tcase 'cc':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tfunction loadScript( script_link, anonymous, integrity ) {\n\t\treturn new Promise( ( resolve, reject ) => {\n\t\t\tconst scriptNode = document.createElement( 'script' );\n\t\t\tscriptNode.src = script_link;\n\t\t\tif ( integrity ) {\n\t\t\t\tscriptNode.integrity = integrity;\n\t\t\t}\n\t\t\tif ( anonymous ) {\n\t\t\t\tscriptNode.crossOrigin = 'anonymous';\n\t\t\t}\n\t\t\tscriptNode.onload = resolve;\n\t\t\tscriptNode.onerror = ( error ) => {\n\t\t\t\tmw.donationInterface.validation.showErrors(\n\t\t\t\t\t{ general: 'Could not load payment provider Javascript. Please reload or try again later.' }\n\t\t\t\t);\n\t\t\t\treject( error );\n\t\t\t};\n\t\t\tdocument.body.append( scriptNode );\n\t\t} );\n\t}\n\n\t/**\n\t * Load an array of script sources (without integrity hashes or crossorigin attributes)\n\t *\n\t * @param {string[]} srcArray\n\t * @return {Promise|*}\n\t */\n\tfunction loadScripts( srcArray ) {\n\t\t// Array.map by default sends three arguments to the callback function - the\n\t\t// actual array element, the index, and then the whole array. We wrap loadScript\n\t\t// in another function here so loadScript only receives the first of those.\n\t\treturn Promise.all( srcArray.map( ( script ) => loadScript( script ) ) );\n\t}\n\n\t/**\n\t * Loads a series of script files in the order specified by the provided array of source URLs.\n\t * Ensures that each script is fully loaded and executed before the next one begins loading.\n\t *\n\t * @param {string[]} srcArray\n\t * @return {Promise}\n\t */\n\tfunction loadScriptsInOrder( srcArray ) {\n\t\tconst scripts = Array.isArray( srcArray ) ? srcArray : [];\n\t\treturn scripts.reduce(\n\t\t\t( chain, src ) => chain.then( () => loadScript( src ) ),\n\t\t\tPromise.resolve()\n\t\t);\n\t}\n\n\tfunction simpleHash( str ) {\n\t\tlet hash = 0;\n\t\tfor ( let i = 0; i < str.length; i++ ) {\n\t\t\tconst char = str.charCodeAt( i );\n\t\t\t// eslint-disable-next-line\n\t\t\thash = ( hash << 5 ) - hash + char;\n\t\t}\n\t\t// Convert to 32bit unsigned integer in base 36 and pad with \"0\" to ensure length is 7.\n\t\t// eslint-disable-next-line\n\t\treturn ( hash >>> 0 ).toString( 36 ).padStart( 7, '0' );\n\t}\n\n\tfunction setBinHash( clearBin ) {\n\t\t$( '#bin_hash' ).val( simpleHash( clearBin ) );\n\t}\n\n\tfunction elementIsVisible( inputElement ) {\n\t\tconst style = window.getComputedStyle( inputElement );\n\t\treturn style.display !== 'none' &&\n\t\tstyle.visibility !== 'hidden' &&\n\t\tstyle.opacity !== 0 &&\n\t\tinputElement.type !== 'hidden' &&\n\t\tinputElement.offsetParent !== null;\n\t}\n\n\tfunction focusOnFirstInput() {\n\t\tconst inputFields = Array.from( document.querySelector( '#payment-form' ).querySelectorAll( 'input, select' ) );\n\t\tconst visibleInputs = inputFields.filter( ( el ) => elementIsVisible( el ) );\n\t\tif ( visibleInputs.length > 0 ) {\n\t\t\tvisibleInputs[ 0 ].focus();\n\t\t}\n\t}\n\n\tfunction hasCheckedSubmethodOption() {\n\t\treturn $( 'input[name=\"payment_submethod\"]:visible:checked' ).length > 0;\n\t}\n\n\tfunction validateAndSubmit( e ) {\n\t\tconst $visibleSubmethods = $( 'input[name=\"payment_submethod\"]:visible' );\n\t\tif ( $visibleSubmethods.length > 1 && $visibleSubmethods.filter( ':checked' ).length === 0 ) {\n\t\t\te.preventDefault();\n\t\t\t$visibleSubmethods.first().focus().prop( 'checked', true );\n\t\t}\n\t\tif ( di.validation.validate() ) {\n\t\t\tdi.forms.submit();\n\t\t} else if ( hasCheckedSubmethodOption() ) {\n\t\t\tdi.forms.resetSubmethod();\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// FIXME: move function declarations into object\n\tdi.forms = {\n\t\tdisable: disableForm,\n\t\tdisableInput: disableInput,\n\t\tenable: enableForm,\n\t\tenableInput: enableInput,\n\t\tclean: cleanInput,\n\t\t// Gateways with more complex form submission can overwrite this\n\t\t// property with their own submission function.\n\t\tsubmit: submitForm,\n\t\tcallDonateApi: callDonateApi,\n\t\tisIframe: isIframe,\n\t\tresetSubmethod: resetSubmethod,\n\t\tgetOptIn: getOptIn,\n\t\tloadScript: loadScript,\n\t\tloadScripts: loadScripts,\n\t\tloadScriptsInOrder: loadScriptsInOrder,\n\t\tsetBinHash: setBinHash,\n\t\tvalidateAndSubmit: validateAndSubmit,\n\t\tdebugMessages: [],\n\t\taddDebugMessage: function ( message ) {\n\t\t\tdi.forms.debugMessages.push( message );\n\t\t}\n\t};\n\n\t$( () => {\n\n\t\tconst $emailDiv = $( '#email' ).closest( 'div' ),\n\t\t\temailExplainMessage = mw.msg( 'donate_interface-email-explain' ),\n\t\t\toptInValue = mw.donationInterface.forms.getOptIn(),\n\t\t\thasSetClientVariablesError = mw.config.get( 'DonationInterfaceSetClientVariablesError' );\n\n\t\tif ( hasSetClientVariablesError ) {\n\t\t\tlocation.assign( mw.config.get( 'DonationInterfaceFailUrl' ) );\n\t\t\treturn;\n\t\t}\n\n\t\tfocusOnFirstInput(); //T410787 T149803\n\n\t\t// If submethods are visible, and a submethod is already selected on\n\t\t// page load, clear it.\n\t\tif ( hasCheckedSubmethodOption() ) {\n\t\t\tdi.forms.resetSubmethod();\n\t\t}\n\n\t\t// Continue button behaviour: require at least one submethod selected when none\n\t\t$( '#paymentContinueBtn' ).on( 'click', validateAndSubmit );\n\n\t\t// Only load employer autocomplete js when the employer field is visible\n\t\tif ( $( '#employer' ).length ) {\n\t\t\tmw.loader.load( 'ext.donationInterface.employerAutoComplete' );\n\t\t}\n\n\t\t// Magic to hopefully disable the spinner in case we are returned to this\n\t\t// page via the Back button.\n\t\t$( window ).on(\n\t\t\t'unload', () => {\n\t\t\t\t// wrapped in case it is overwritten\n\t\t\t\tdi.forms.enable();\n\t\t\t\tdi.forms.enableInput();\n\t\t\t}\n\t\t);\n\n\t\tfunction showEmailExplain() {\n\t\t\t$emailDiv.after( '<div id=\"email_explain\">' + emailExplainMessage + '</div>' );\n\t\t}\n\n\t\tif ( optInValue === '0' ) {\n\t\t\tshowEmailExplain();\n\t\t}\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.jaVariant02.js","messages":[{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"mw\" type.","line":8,"column":1,"nodeType":"Block","endLine":8,"endColumn":1},{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"$\" type.","line":9,"column":1,"nodeType":"Block","endLine":9,"endColumn":1}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Experiment to determine whether different placeholder text and extra name\n * fields improve donation rates in Japan. Once tests are concluded and optimal\n * text is decided, please make the optimal text standard and delete this and\n * the extension.json module configuration for ext.donationInterface.jaVariant02\n * and ext.donationInterface.adyenCheckoutWithJaVariant02.\n *\n * @param mw\n * @param $\n */\n\n( function ( mw, $ ) {\n\tmw.donationInterface = mw.donationInterface || {};\n\tmw.donationInterface.getExtraData = function () {\n\t\treturn {\n\t\t\tfirst_name_phonetic: $( '#first_name_phonetic' ).val(),\n\t\t\tlast_name_phonetic: $( '#last_name_phonetic' ).val()\n\t\t};\n\t};\n} )( mediaWiki, jQuery );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvert.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'mc' is never reassigned. Use 'const' instead.","line":2,"column":6,"nodeType":"Identifier","messageId":"useConst","endLine":2,"endColumn":8},{"ruleId":"prefer-const","severity":1,"message":"'tyUrl' is never reassigned. Use 'const' instead.","line":6,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":8},{"ruleId":"prefer-const","severity":1,"message":"'convertAmounts' is never reassigned. Use 'const' instead.","line":9,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":9,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'numAmounts' is never reassigned. Use 'const' instead.","line":17,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":17,"endColumn":13},{"ruleId":"no-shadow","severity":1,"message":"'currency' is already declared in the upper scope on line 3 column 3.","line":37,"column":49,"nodeType":"Identifier","messageId":"noShadow","endLine":37,"endColumn":57},{"ruleId":"no-shadow","severity":1,"message":"'currency' is already declared in the upper scope on line 3 column 3.","line":78,"column":39,"nodeType":"Identifier","messageId":"noShadow","endLine":78,"endColumn":47},{"ruleId":"no-shadow","severity":1,"message":"'currency' is already declared in the upper scope on line 3 column 3.","line":147,"column":51,"nodeType":"Identifier","messageId":"noShadow","endLine":147,"endColumn":59},{"ruleId":"prefer-const","severity":1,"message":"'rates' is never reassigned. Use 'const' instead.","line":148,"column":7,"nodeType":"Identifier","messageId":"useConst","endLine":148,"endColumn":12},{"ruleId":"prefer-const","severity":1,"message":"'amountRules' is never reassigned. Use 'const' instead.","line":149,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":149,"endColumn":15},{"ruleId":"prefer-const","severity":1,"message":"'$smallAmountMessage' is never reassigned. Use 'const' instead.","line":151,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":151,"endColumn":23},{"ruleId":"prefer-const","severity":1,"message":"'formattedMin' is never reassigned. Use 'const' instead.","line":161,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":161,"endColumn":15},{"ruleId":"prefer-const","severity":1,"message":"'locale' is never reassigned. Use 'const' instead.","line":177,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":177,"endColumn":10},{"ruleId":"prefer-const","severity":1,"message":"'presetAmount' is never reassigned. Use 'const' instead.","line":180,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":180,"endColumn":15}],"suppressedMessages":[{"ruleId":"no-jquery/no-fade","severity":2,"message":"Prefer CSS transitions to .fadeOut","line":225,"column":6,"nodeType":"CallExpression","endLine":231,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-fade","severity":2,"message":"Prefer CSS transitions to .fadeIn","line":226,"column":7,"nodeType":"CallExpression","endLine":228,"endColumn":10,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-fade","severity":2,"message":"Prefer CSS transitions to .fadeIn","line":229,"column":7,"nodeType":"CallExpression","endLine":229,"endColumn":31,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-fade","severity":2,"message":"Prefer CSS transitions to .fadeOut","line":236,"column":6,"nodeType":"CallExpression","endLine":236,"endColumn":31,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-fade","severity":2,"message":"Prefer CSS transitions to .fadeOut","line":237,"column":6,"nodeType":"CallExpression","endLine":239,"endColumn":9,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"no-jquery/no-fade","severity":2,"message":"Prefer CSS transitions to .fadeIn","line":238,"column":7,"nodeType":"CallExpression","endLine":238,"endColumn":33,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":13,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $, mw ) {\n\tlet mc = {},\n\t\tcurrency,\n\t\toriginalAmount,\n\t\t// These config vars are set in GatewayPage::setClientVariables\n\t\ttyUrl = mw.config.get( 'wgDonationInterfaceThankYouUrl' ),\n\t\t// This is set to the ask amounts for the selected currency, or null\n\t\t// if there are no amounts set for it.\n\t\tconvertAmounts = mw.config.get( 'wgDonationInterfaceMonthlyConvertAmounts' );\n\n\tmc.getConvertAsk = function ( amount ) {\n\t\tlet i,\n\t\t\tnumAmounts;\n\t\tif ( !convertAmounts ) {\n\t\t\treturn 0;\n\t\t}\n\t\tnumAmounts = convertAmounts.length;\n\t\tfor ( i = 0; i < numAmounts; i++ ) {\n\t\t\tif ( amount <= convertAmounts[ i ][ 0 ] ) {\n\t\t\t\treturn convertAmounts[ i ][ 1 ];\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t};\n\n\tmc.focusModel = function () {\n\t\t$( '#mcModalTitle' ).attr( 'tabindex', '-1' );\n\t\tsetTimeout( () => {\n\t\t\t$( '.mc-modal' ).focus();\n\t\t}, 50 );\n\t};\n\n\tmc.focusEditModel = function () {\n\t\t$( '#mcEditTitle' ).attr( 'tabindex', '-1' ).focus();\n\t};\n\n\tmc.setConvertAsk = function ( suggestedAmount, currency, locale ) {\n\t\tconst convertAmountFormatted = mc.formatAmount(\n\t\t\tsuggestedAmount, currency, locale\n\t\t);\n\t\t$( '.mc-convert-ask' ).text( convertAmountFormatted );\n\t};\n\n\tmc.showModal = function () {\n\t\tconst cookieDomains = [\n\t\t\t'en.wikipedia.org',\n\t\t\t'en.wiktionary.org',\n\t\t\t'en.wikisource.org',\n\t\t\t'en.wikibooks.org',\n\t\t\t'en.wikiversity.org',\n\t\t\t'en.wikiquote.org',\n\t\t\t'en.wikinews.org',\n\t\t\t'meta.wikimedia.org',\n\t\t\t'commons.wikimedia.org',\n\t\t\t'species.wikimedia.org',\n\t\t\t'www.mediawiki.org',\n\t\t\t'www.wikidata.org',\n\t\t\t'en.wikivoyage.org'\n\t\t];\n\t\tconst cookieImgDiv = document.querySelector( 'div#hide-cookies' );\n\t\tlet img;\n\t\t$( '.mc-modal-screen' ).show();\n\t\tfor ( let i = 0; i < cookieDomains.length; i++ ) {\n\t\t\timg = document.createElement( 'img' );\n\t\t\timg.setAttribute( 'height', '1' );\n\t\t\timg.setAttribute( 'width', '1' );\n\t\t\timg.setAttribute( 'tabindex', '-1' );\n\t\t\timg.setAttribute( 'aria-hidden', 'true' );\n\t\t\timg.setAttribute( 'alt', '' );\n\t\t\timg.setAttribute(\n\t\t\t\t'src',\n\t\t\t\t'//' + cookieDomains[ i ] + '/w/index.php?title=Special:HideBanners&category=fundraising&reason=donate'\n\t\t\t);\n\t\t\tcookieImgDiv.append( img );\n\t\t}\n\t};\n\n\tmc.formatAmount = function ( amount, currency, locale ) {\n\t\tlet formattedAmount;\n\n\t\ttry {\n\t\t\tformattedAmount = amount.toLocaleString(\n\t\t\t\tlocale,\n\t\t\t\t{\n\t\t\t\t\tcurrency: currency,\n\t\t\t\t\tstyle: 'currency'\n\t\t\t\t}\n\t\t\t);\n\t\t} catch ( e ) {\n\t\t\t// Assume a two decimal place currency for fallback\n\t\t\tformattedAmount = currency + ' ' + amount.toFixed( 2 );\n\t\t}\n\t\treturn formattedAmount;\n\t};\n\n\tmc.getSendData = function ( amount ) {\n\t\treturn {\n\t\t\taction: 'di_recurring_convert',\n\t\t\tformat: 'json',\n\t\t\tgateway: $( '#gateway' ).val(),\n\t\t\twmf_token: $( '#wmf_token' ).val(),\n\t\t\tamount: amount\n\t\t};\n\t};\n\n\tmc.postMonthlyConvertDonate = function ( amount, declineMonthlyConvert ) {\n\t\tconst sendData = mc.getSendData( amount );\n\t\tif ( declineMonthlyConvert ) {\n\t\t\tsendData.declineMonthlyConvert = declineMonthlyConvert;\n\t\t}\n\t\t$.ajax( {\n\t\t\turl: mw.util.wikiScript( 'api' ),\n\t\t\tdata: sendData,\n\t\t\tdataType: 'json',\n\t\t\ttype: 'POST',\n\t\t\tsuccess: function ( data ) {\n\t\t\t\tif ( data && !data.error && data.result && !data.result.errors ) {\n\t\t\t\t\tconst url = new URL( tyUrl, location.href );\n\t\t\t\t\tif ( !declineMonthlyConvert ) {\n\t\t\t\t\t\turl.searchParams.set( 'recurringConversion', 1 );\n\t\t\t\t\t}\n\t\t\t\t\tif ( sendData.frequency_unit ) {\n\t\t\t\t\t\turl.searchParams.set( 'frequency_unit', sendData.frequency_unit );\n\t\t\t\t\t}\n\t\t\t\t\tdocument.location.assign( url.toString() );\n\t\t\t\t} else {\n\t\t\t\t\t// FIXME - alert sux. Not much donor can do at this point.\n\t\t\t\t\t// We should let 'em know the recurring conversion failed\n\t\t\t\t\t// but the initial donation worked, then show them the thank\n\t\t\t\t\t// you page.\n\t\t\t\t\tif ( !declineMonthlyConvert ) {\n\t\t\t\t\t\talert( mw.msg( 'donate_interface-monthly-convert-error' ) );\n\t\t\t\t\t}\n\t\t\t\t\tdocument.location.assign( tyUrl );\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function () {\n\t\t\t\t// FIXME too\n\t\t\t\tif ( !declineMonthlyConvert ) {\n\t\t\t\t\talert( mw.msg( 'donate_interface-monthly-convert-error' ) );\n\t\t\t\t}\n\t\t\t\tdocument.location.assign( tyUrl );\n\t\t\t}\n\t\t} );\n\t};\n\n\tmc.setSmallAmountMessageAndMinLocal = function ( currency, locale ) {\n\t\tlet rates = mw.config.get( 'wgDonationInterfaceCurrencyRates' ),\n\t\t\tamountRules = mw.config.get( 'wgDonationInterfaceAmountRules' ),\n\t\t\tformattedMin,\n\t\t\t$smallAmountMessage = $( '#mc-error-smallamount' );\n\n\t\tif ( currency === amountRules.currency || ( typeof rates[ currency ] ) === 'undefined' ) {\n\t\t\tmc.minLocal = amountRules.min;\n\t\t} else {\n\t\t\t// Rates are all relative to USD, so we divide the configured minimum by its corresponding\n\t\t\t// rate to get the minimum in USD, then multiply by the rate of the donation currency to get\n\t\t\t// the minimum in the donation currency.\n\t\t\tmc.minLocal = amountRules.min / rates[ amountRules.currency ] * rates[ currency ];\n\t\t}\n\t\tformattedMin = mc.formatAmount(\n\t\t\tmc.minLocal, currency, locale\n\t\t);\n\t\t$smallAmountMessage.text(\n\t\t\t$smallAmountMessage.text().replace( '$1', formattedMin )\n\t\t);\n\t};\n\n\t// TODO Unify logic for determining whether or not to show monthly convert. This\n\t// is just a sanity check to see if the required DOM elements are there.\n\tmc.canShowModal = function () {\n\t\treturn $( '.mc-modal-screen' ).length > 0;\n\t};\n\n\tmc.init = function () {\n\t\tlet presetAmount,\n\t\t\tlocale = $( '#language' ).val() + '-' + $( '#country' ).val();\n\t\toriginalAmount = +$( '#amount' ).val();\n\t\tcurrency = $( '#currency' ).val();\n\t\tpresetAmount = mc.presetAmount || mc.getConvertAsk( originalAmount );\n\t\tif ( presetAmount === 0 && tyUrl !== null ) {\n\t\t\t// They're donating in an unsupported currency, or are\n\t\t\t// outside of the range where it makes sense to ask for\n\t\t\t// a monthly donation. Just send them to the TY page.\n\t\t\tdocument.location.assign( tyUrl );\n\t\t} else {\n\t\t\tmc.presetAmount = presetAmount;\n\t\t\tmc.setConvertAsk(\n\t\t\t\tpresetAmount,\n\t\t\t\tcurrency,\n\t\t\t\tlocale\n\t\t\t);\n\t\t\tmc.showModal();\n\t\t\tmc.focusModel();\n\t\t\tmc.setSmallAmountMessageAndMinLocal( currency, locale );\n\t\t\t$( '.mc-no-button, .mc-close' ).on( 'click keypress', ( e ) => {\n\t\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\t\tmc.postMonthlyConvertDonate( presetAmount, true );\n\t\t\t\t}\n\t\t\t} );\n\t\t\t$( '.mc-yes-button' ).on( 'click keypress', ( e ) => {\n\t\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\t\tmc.postMonthlyConvertDonate( presetAmount );\n\t\t\t\t}\n\t\t\t} );\n\t\t\t$( '.mc-donate-monthly-button' ).on( 'click keypress', ( e ) => {\n\t\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\t\tconst $otherAmountField = $( '#mc-other-amount-input' ),\n\t\t\t\t\t\totherAmount = +$otherAmountField.val(),\n\t\t\t\t\t\t$smallAmountMessage = $( '#mc-error-smallamount' );\n\n\t\t\t\t\tif ( otherAmount < mc.minLocal ) {\n\t\t\t\t\t\t$otherAmountField.addClass( 'errorHighlight' );\n\t\t\t\t\t\t$smallAmountMessage.show();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$smallAmountMessage.hide();\n\t\t\t\t\t\t$otherAmountField.removeClass( 'errorHighlight' );\n\t\t\t\t\t\tmc.postMonthlyConvertDonate( otherAmount );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t\t/* eslint-disable no-jquery/no-fade */\n\t\t\t$( '.mc-diff-amount-link' ).on( 'click keypress', ( e ) => {\n\t\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\t\t$( '.mc-choice' ).fadeOut( () => {\n\t\t\t\t\t\t$( '.mc-edit-amount' ).fadeIn( () => {\n\t\t\t\t\t\t\tmc.focusEditModel();\n\t\t\t\t\t\t} );\n\t\t\t\t\t\t$( '.mc-back' ).fadeIn();\n\t\t\t\t\t\t$( '.mc-other-amount-input' ).focus();\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t\t$( '.mc-back' ).on( 'click keypress', ( e ) => {\n\t\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\t\t$( '.mc-back' ).fadeOut();\n\t\t\t\t\t$( '.mc-edit-amount' ).fadeOut( () => {\n\t\t\t\t\t\t$( '.mc-choice' ).fadeIn();\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t\t/* eslint-enable no-jquery/no-fade */\n\t\t}\n\n\t};\n\t$( () => {\n\t\tif ( mw.config.get( 'showMConStartup' ) ) {\n\t\t\tmc.init();\n\t\t}\n\t} );\n\tmw.monthlyConvert = mc;\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvertAnnual.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'mc' is never reassigned. Use 'const' instead.","line":3,"column":7,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":9},{"ruleId":"prefer-const","severity":1,"message":"'originalGetSendData' is never reassigned. Use 'const' instead.","line":3,"column":31,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":50},{"ruleId":"prefer-const","severity":1,"message":"'originalAmount' is never reassigned. Use 'const' instead.","line":4,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":4,"endColumn":18},{"ruleId":"prefer-const","severity":1,"message":"'$otherAmountMonthlyInput' is never reassigned. Use 'const' instead.","line":5,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":5,"endColumn":28},{"ruleId":"prefer-const","severity":1,"message":"'$otherAmountAnnualInput' is never reassigned. Use 'const' instead.","line":5,"column":62,"nodeType":"Identifier","messageId":"useConst","endLine":5,"endColumn":85},{"ruleId":"prefer-const","severity":1,"message":"'$otherMonthlySubmit' is never reassigned. Use 'const' instead.","line":6,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":23},{"ruleId":"prefer-const","severity":1,"message":"'$otherAnnualSubmit' is never reassigned. Use 'const' instead.","line":6,"column":60,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":78},{"ruleId":"prefer-const","severity":1,"message":"'$smallAmountMessage' is never reassigned. Use 'const' instead.","line":7,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":7,"endColumn":23},{"ruleId":"prefer-const","severity":1,"message":"'originalAmountFormatted' is never reassigned. Use 'const' instead.","line":15,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":15,"endColumn":26}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":9,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $, mw ) {\n\t$( () => {\n\t\tlet mc = mw.monthlyConvert, originalGetSendData = mc.getSendData, frequencyUnit = 'month',\n\t\t\toriginalAmount = Number( $( '#amount' ).val() ), originalAmountFormatted,\n\t\t\t$otherAmountMonthlyInput = $( '#mc-other-amount-input' ), $otherAmountAnnualInput = $( '#mc-other-amount-input-annual' ),\n\t\t\t$otherMonthlySubmit = $( '.mc-donate-monthly-button' ), $otherAnnualSubmit = $( '.mc-donate-annual-button' ),\n\t\t\t$smallAmountMessage = $( '#mc-error-smallamount' );\n\n\t\tmc.getSendData = function ( amount ) {\n\t\t\tconst data = originalGetSendData( amount );\n\t\t\tdata.frequency_unit = frequencyUnit;\n\t\t\treturn data;\n\t\t};\n\n\t\toriginalAmountFormatted = mc.formatAmount(\n\t\t\toriginalAmount,\n\t\t\t$( '#currency' ).val(),\n\t\t\t$( '#language' ).val() + '-' + $( '#country' ).val()\n\t\t);\n\n\t\t$( '.mc-convert-ask-annual' ).text( originalAmountFormatted );\n\t\t$( '#mc-yes-button-monthly' ).on( 'click keypress', ( e ) => {\n\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\tfrequencyUnit = 'month';\n\t\t\t\tmc.postMonthlyConvertDonate( mc.presetAmount );\n\t\t\t}\n\t\t} );\n\t\t$( '#mc-yes-button-annual' ).on( 'click keypress', ( e ) => {\n\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\tfrequencyUnit = 'year';\n\t\t\t\tmc.postMonthlyConvertDonate( originalAmount );\n\t\t\t}\n\t\t} );\n\t\t$otherAmountMonthlyInput.on( 'keyup', () => {\n\t\t\tconst otherAmount = Number( $otherAmountMonthlyInput.val() );\n\t\t\tif ( otherAmount > 0 ) {\n\t\t\t\tfrequencyUnit = 'month';\n\t\t\t\t$otherAmountAnnualInput.val( '' ).removeClass( 'errorHighlight' );\n\t\t\t\t$otherMonthlySubmit.show();\n\t\t\t\t$otherAnnualSubmit.hide();\n\t\t\t\t$smallAmountMessage.hide();\n\t\t\t}\n\t\t} );\n\t\t$otherAmountAnnualInput.on( 'keyup', () => {\n\t\t\tconst otherAmount = Number( $otherAmountAnnualInput.val() );\n\t\t\tif ( otherAmount > 0 ) {\n\t\t\t\tfrequencyUnit = 'year';\n\t\t\t\t$otherAmountMonthlyInput.val( '' ).removeClass( 'errorHighlight' );\n\t\t\t\t$otherAnnualSubmit.show();\n\t\t\t\t$otherMonthlySubmit.hide();\n\t\t\t\t$smallAmountMessage.hide();\n\t\t\t}\n\t\t} );\n\t\t$otherAnnualSubmit.on( 'click keypress', ( e ) => {\n\t\t\tif ( e.which === 13 || e.type === 'click' ) {\n\t\t\t\tconst otherAmount = Number( $otherAmountAnnualInput.val() );\n\n\t\t\t\tif ( otherAmount < mc.minLocal ) {\n\t\t\t\t\t$otherAmountAnnualInput.addClass( 'errorHighlight' );\n\t\t\t\t\t$smallAmountMessage.show();\n\t\t\t\t} else {\n\t\t\t\t\t$smallAmountMessage.hide();\n\t\t\t\t\t$otherAmountAnnualInput.removeClass( 'errorHighlight' );\n\t\t\t\t\tmc.postMonthlyConvertDonate( otherAmount );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvertButtonFlip.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvertMultiplier.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'mc' is never reassigned. Use 'const' instead.","line":3,"column":7,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":9},{"ruleId":"prefer-const","severity":1,"message":"'originalAmount' is never reassigned. Use 'const' instead.","line":4,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":4,"endColumn":17}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $ ) {\n\t$( () => {\n\t\tlet mc = mw.monthlyConvert, originalAmount, presetAmount;\n\t\toriginalAmount = parseFloat( $( '#amount' ).val() );\n\t\tpresetAmount = mc.getConvertAsk( originalAmount );\n\t\tpresetAmount = ( presetAmount * 1.1 ).toFixed( 2 ); // Rounds to 2 decimal places\n\t\tpresetAmount = parseFloat( presetAmount ); // Converts back to a number\n\t\tmc.presetAmount = presetAmount;\n\t} );\n} )( jQuery );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvert_003.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvert_010.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvert_011.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'mc' is never reassigned. Use 'const' instead.","line":3,"column":7,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":9},{"ruleId":"prefer-const","severity":1,"message":"'locale' is never reassigned. Use 'const' instead.","line":4,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":4,"endColumn":10},{"ruleId":"prefer-const","severity":1,"message":"'originalAmount' is never reassigned. Use 'const' instead.","line":5,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":5,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'currency' is never reassigned. Use 'const' instead.","line":6,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":11},{"ruleId":"prefer-const","severity":1,"message":"'presetAmount' is never reassigned. Use 'const' instead.","line":7,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":7,"endColumn":15},{"ruleId":"prefer-const","severity":1,"message":"'formattedAsk' is never reassigned. Use 'const' instead.","line":8,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":8,"endColumn":15}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $, mw ) {\n\t$( () => {\n\t\tlet mc = mw.monthlyConvert, originalAmount, currency, formattedAsk, presetAmount,\n\t\t\tlocale = $( '#language' ).val() + '-' + $( '#country' ).val();\n\t\toriginalAmount = +$( '#amount' ).val();\n\t\tcurrency = $( '#currency' ).val();\n\t\tpresetAmount = mc.getConvertAsk( originalAmount );\n\t\tformattedAsk = mc.formatAmount(\n\t\t\tpresetAmount, currency, locale\n\t\t);\n\t\t$( '.mc-no-button' ).text(\n\t\t\tmw.msg( 'donate_interface-monthly-convert-no-button-variant-011' )\n\t\t);\n\t\t$( '.mc-yes-button' ).text(\n\t\t\tmw.msg( 'donate_interface-monthly-convert-yes-button-variant-011' ).replace(\n\t\t\t\t'<span class=\\\"mc-convert-ask\\\"></span>', formattedAsk\n\t\t\t)\n\t\t);\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.monthlyConvert_015.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.recurUpgrade.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'$submitButton' is never reassigned. Use 'const' instead.","line":3,"column":7,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":20},{"ruleId":"prefer-const","severity":1,"message":"'$amountField' is never reassigned. Use 'const' instead.","line":4,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":4,"endColumn":16},{"ruleId":"prefer-const","severity":1,"message":"'$otherAmountField' is never reassigned. Use 'const' instead.","line":5,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":5,"endColumn":21},{"ruleId":"prefer-const","severity":1,"message":"'$totalMessage' is never reassigned. Use 'const' instead.","line":6,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":6,"endColumn":17},{"ruleId":"prefer-const","severity":1,"message":"'$newTotalAmount' is never reassigned. Use 'const' instead.","line":7,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":7,"endColumn":19},{"ruleId":"prefer-const","severity":1,"message":"'$form' is never reassigned. Use 'const' instead.","line":8,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":8,"endColumn":9},{"ruleId":"prefer-const","severity":1,"message":"'originalAmount' is never reassigned. Use 'const' instead.","line":9,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":9,"endColumn":18},{"ruleId":"prefer-const","severity":1,"message":"'currency' is never reassigned. Use 'const' instead.","line":10,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":10,"endColumn":12},{"ruleId":"prefer-const","severity":1,"message":"'maximum' is never reassigned. Use 'const' instead.","line":11,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":11,"endColumn":11},{"ruleId":"prefer-const","severity":1,"message":"'nextDateFormatted' is never reassigned. Use 'const' instead.","line":12,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":12,"endColumn":21},{"ruleId":"prefer-const","severity":1,"message":"'preSelectAmount' is never reassigned. Use 'const' instead.","line":14,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":14,"endColumn":19},{"ruleId":"prefer-const","severity":1,"message":"'valueIsValid' is never reassigned. Use 'const' instead.","line":38,"column":4,"nodeType":"Identifier","messageId":"useConst","endLine":38,"endColumn":16}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":12,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $ ) {\n\t$( () => {\n\t\tlet $submitButton = $( '#save' ),\n\t\t\t$amountField = $( 'input[name=upgrade_amount]' ),\n\t\t\t$otherAmountField = $( 'input[name=upgrade_amount_other]' ),\n\t\t\t$totalMessage = $( '.recurUpgradeMessageToggle' ),\n\t\t\t$newTotalAmount = $( '.recurUpgradeMessageToggle strong' ),\n\t\t\t$form = $( 'form' ),\n\t\t\toriginalAmount = +( $form.attr( 'data-original-amount' ) ),\n\t\t\tcurrency = $form.attr( 'data-currency' ),\n\t\t\tmaximum = +( $form.attr( 'data-maximum' ) ),\n\t\t\tnextDateFormatted = $form.attr( 'data-next-date-formatted' ),\n\t\t\tformatter,\n\t\t\tpreSelectAmount = ( new URLSearchParams( document.location.search ) ).get( 'preSelect' );\n\n\t\t// Avoid console errors in case currency is not supplied\n\t\tif ( currency && currency.length === 3 ) {\n\t\t\tformatter = new Intl.NumberFormat(\n\t\t\t\t$form.attr( 'data-locale' ), {\n\t\t\t\t\tstyle: 'currency',\n\t\t\t\t\tcurrency: $form.attr( 'data-currency' )\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tfunction setTotalAndSubmitState() {\n\t\t\tlet valueIsValid,\n\t\t\t\tvalue = $amountField.filter( ':checked' ).val(),\n\t\t\t\tformattedValue;\n\n\t\t\tif ( value === 'other' ) {\n\t\t\t\tvalue = $otherAmountField.val();\n\t\t\t} else {\n\t\t\t\t$otherAmountField.val( '' );\n\t\t\t}\n\t\t\t// Use unary + operator to tell JS to treat it as a number, not a string\n\t\t\tvalue = +value;\n\t\t\tvalueIsValid = ( value > 0 && value <= maximum );\n\n\t\t\tif ( valueIsValid ) {\n\t\t\t\tformattedValue = formatter.format( originalAmount + value );\n\t\t\t\t$submitButton.removeClass( 'disabled' );\n\t\t\t\t$submitButton.prop( 'disabled', false );\n\t\t\t\tif ( $newTotalAmount.length > 0 ) {\n\t\t\t\t\t$newTotalAmount.text( formattedValue );\n\t\t\t\t} else {\n\t\t\t\t\t$totalMessage.text( mw.message( 'recurupgrade-upgrading-new-amount-and-date',\n\t\t\t\t\t\tformattedValue,\n\t\t\t\t\t\tnextDateFormatted\n\t\t\t\t\t) );\n\t\t\t\t}\n\t\t\t\t$totalMessage.show();\n\t\t\t} else {\n\t\t\t\t$submitButton.addClass( 'disabled' );\n\t\t\t\t$submitButton.prop( 'disabled', true );\n\t\t\t\t$totalMessage.hide();\n\t\t\t}\n\t\t}\n\n\t\t$amountField.change( setTotalAndSubmitState );\n\t\t$otherAmountField.on( 'change keypress', ( e ) => {\n\t\t\t// numbers only to get Firefox and Safari to behave\n\t\t\t// this code is also used in donate wiki's other amount field\n\t\t\t// T389066\n\t\t\tconst chr = String.fromCharCode( e.which );\n\t\t\tif ( !'0123456789., '.includes( chr ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\t\t// We need to use setInterval because the new value of the other amount\n\t\t// field is not immediately available in the keyup handler\n\t\t$otherAmountField.on( 'change keyup', () => {\n\t\t\tsetInterval( setTotalAndSubmitState, 0 );\n\t\t} );\n\t\tif ( preSelectAmount ) {\n\t\t\t$amountField.filter( '[value=' + preSelectAmount + ']' ).prop( 'checked', true );\n\t\t\t$amountField.filter( '[value!=' + preSelectAmount + ']' ).prop( 'checked', false );\n\t\t}\n\t\t$otherAmountField.focus( () => {\n\t\t\t$amountField.filter( '[value=other]' ).prop( 'checked', true );\n\t\t\tsetTotalAndSubmitState();\n\t\t} );\n\t\tsetTotalAndSubmitState();\n\t} );\n} )( jQuery );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.requestNewChecksumLink.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/ext.donationInterface.validation.js","messages":[{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"$\" type.","line":7,"column":1,"nodeType":"Block","endLine":7,"endColumn":1},{"ruleId":"jsdoc/require-param-type","severity":1,"message":"Missing JSDoc @param \"mw\" type.","line":8,"column":1,"nodeType":"Block","endLine":8,"endColumn":1},{"ruleId":"prefer-const","severity":1,"message":"'di' is never reassigned. Use 'const' instead.","line":11,"column":6,"nodeType":"Identifier","messageId":"useConst","endLine":11,"endColumn":8},{"ruleId":"prefer-const","severity":1,"message":"'mcDomains' is never reassigned. Use 'const' instead.","line":13,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":13,"endColumn":12},{"ruleId":"prefer-const","severity":1,"message":"'multiCountrySubdomains' is never reassigned. Use 'const' instead.","line":33,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":33,"endColumn":25},{"ruleId":"prefer-const","severity":1,"message":"'countryTlds' is never reassigned. Use 'const' instead.","line":34,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":34,"endColumn":14},{"ruleId":"no-shadow","severity":1,"message":"'i' is already declared in the upper scope on line 39 column 36.","line":40,"column":26,"nodeType":"Identifier","messageId":"noShadow","endLine":40,"endColumn":27}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":7,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* globals Mailcheck */\n/**\n * Client-side validation logic for DonationInterface\n * For starters, we just redirect to the existing global functions.\n * They should be rewritten here when we modernize the remaining forms.\n *\n * @param $\n * @param mw\n */\n( function ( $, mw ) {\n\tlet di = mw.donationInterface = mw.donationInterface || {},\n\t\tcheckMail = true,\n\t\tmcDomains = Mailcheck.defaultDomains.concat( [\n\t\t\t'aim.com', 'alice.it', 'aon.at', 'bellsouth.net', 'bigpond.com',\n\t\t\t'bigpond.net.au', 'blueyonder.co.uk', 'btinternet.com',\n\t\t\t'btopenworld.com', 'charter.net', 'cox.net', 'docomo.ne.jp',\n\t\t\t'earthlink.net', 'email.it', 'embarqmail.com', 'ezweb.ne.jp',\n\t\t\t'fastwebnet.it', 'free.fr', 'frontier.com', 'gmx.at', 'gmx.de',\n\t\t\t'gmx.net', 'hetnet.nl', 'home.nl', 'i.softbank.jp', 'iinet.net.au',\n\t\t\t'inwind.it', 'juno.com', 'laposte.net', 'libero.it',\n\t\t\t'mindspring.com', 'netscape.net', 'neuf.fr', 'nifty.com',\n\t\t\t'ntlworld.com', 'o2.pl', 'online.no', 'optonline.net',\n\t\t\t'optusnet.com.au', 'orange.fr', 'pacbell.net', 'planet.nl',\n\t\t\t'q.com', 'qq.com','roadrunner.com', 'rocketmail.com',\n\t\t\t'rogers.com', 'seznam.cz', 'sfr.fr', 'shaw.ca', 'sky.com',\n\t\t\t'skynet.be', 'sympatico.ca', 'talktalk.net', 'telefonica.net',\n\t\t\t'telenet.be', 'telia.com', 'telus.net', 'tin.it',\n\t\t\t'tiscali.co.uk', 'tiscali.it', 'tpg.com.au', 'umich.edu',\n\t\t\t'uol.com.br', 'videotron.ca', 'virgilio.it', 'wanadoo.fr',\n\t\t\t'web.de', 'windstream.net', 'wp.pl', 'xs4all.nl', 'xtra.co.nz',\n\t\t\t'ybb.ne.jp', 'ymail.com', 'ziggo.nl'\n\t\t] ),\n\t\tmultiCountrySubdomains = [ 'yahoo', 'hotmail', 'outlook', 'live' ],\n\t\tcountryTlds = [\n\t\t\t'ca', 'cl', 'co.id', 'co.il', 'co.in', 'co.jp', 'co.uk', 'com', 'com.ar',\n\t\t\t'com.au', 'com.br', 'com.mx', 'com.pe', 'com.sg', 'cz', 'de', 'es',\n\t\t\t'fr', 'it', 'jp', 'kr', 'nl', 'pt', 'se'\n\t\t];\n\t$.each( multiCountrySubdomains, ( i, subdomain ) => {\n\t\t$.each( countryTlds, ( i, countryTld ) => {\n\t\t\tmcDomains.push( subdomain + '.' + countryTld );\n\t\t} );\n\t} );\n\n\tfunction showErrors( errors ) {\n\t\tconst generalErrors = [];\n\n\t\t$.each( errors, ( field, message ) => {\n\t\t\tconst $messageField = $( '#' + field + 'Msg' );\n\n\t\t\tif ( $messageField.length > 0 ) {\n\t\t\t\t$( '#' + field ).addClass( 'errorHighlight' );\n\t\t\t\t$messageField\n\t\t\t\t\t.removeClass( 'errorMsgHide' )\n\t\t\t\t\t.addClass( 'errorMsg' )\n\t\t\t\t\t.text( message );\n\t\t\t} else {\n\t\t\t\tgeneralErrors.push( message );\n\t\t\t}\n\t\t} );\n\t\tif ( generalErrors.length > 0 ) {\n\t\t\t$( '#topError' ).html(\n\t\t\t\tgeneralErrors.join( '<br/>' )\n\t\t\t);\n\t\t\t$( '#errorReference' )\n\t\t\t\t.removeClass( 'errorMsgHide' )\n\t\t\t\t.addClass( 'errorMsg' );\n\t\t}\n\t}\n\n\t/**\n\t * Are any errors currently showing, from either server-side or\n\t * client-side validation?\n\t *\n\t * @return {boolean}\n\t */\n\tfunction hasErrors() {\n\t\treturn $( '.errorMsg' ).length > 0;\n\t}\n\n\tdi.validation = {\n\t\tvalidate: function () {\n\t\t\t// This funkiness is to make sure we run all the validations and\n\t\t\t// highlight bad values, rather than short-circuiting the second\n\t\t\t// group of tests if \"&&\" detects that the first tests failed.\n\t\t\tconst results = [\n\t\t\t\t\tthis.validateAmount(),\n\t\t\t\t\tthis.validatePersonal()\n\t\t\t\t],\n\t\t\t\t// Fail if one or more tests failed.\n\t\t\t\tsuccess = ( !results.includes( false ) );\n\n\t\t\treturn success;\n\t\t},\n\t\t// FIXME: Move global scope functions here\n\t\tvalidateAmount: window.validateAmount,\n\t\tvalidatePersonal: window.validate_personal,\n\t\tshowErrors: showErrors,\n\t\thasErrors: hasErrors\n\t};\n\n\t// Set up email error detection and correction\n\t$( document ).on( 'blur', '#email', function () {\n\t\tif ( !checkMail ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Be really conservative - only catch two letter errors\n\t\tMailcheck.domainThreshold = 2; // No way to set from opts!\n\t\t$( this ).mailcheck( {\n\t\t\ttopLevelDomains: [],\n\t\t\tdomains: mcDomains,\n\t\t\tsuggested: function ( element, suggestion ) {\n\t\t\t\tconst message = mw.msg(\n\t\t\t\t\t'donate_interface-did-you-mean',\n\t\t\t\t\tsuggestion.full\n\t\t\t\t);\n\t\t\t\t$( '#emailSuggestion' ).show();\n\t\t\t\t$( '#emailSuggestion span' ).html( message );\n\t\t\t},\n\t\t\tempty: function ( element ) {\n\t\t\t\t$( '#emailSuggestion' ).hide();\n\t\t\t}\n\t\t} );\n\t} );\n\t$( document ).on( 'click', '#emailSuggestion .correction', function () {\n\t\t$( '#email' ).val( $( this ).text() );\n\t\t$( '#emailSuggestion' ).hide();\n\t} );\n\t$( document ).on( 'click', '#emailSuggestion .close-button', () => {\n\t\tcheckMail = false; // Don't bother them again\n\t\t$( '#emailSuggestion' ).hide();\n\t} );\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/js/skinOverride.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/modules/validate_input.js","messages":[{"ruleId":"jsdoc/require-returns","severity":1,"message":"Missing JSDoc @return declaration.","line":1,"column":1,"nodeType":"Block","endLine":4,"endColumn":4},{"ruleId":"prefer-const","severity":1,"message":"'rates' is never reassigned. Use 'const' instead.","line":9,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":9,"endColumn":8},{"ruleId":"prefer-const","severity":1,"message":"'amountRules' is never reassigned. Use 'const' instead.","line":10,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":10,"endColumn":14},{"ruleId":"prefer-const","severity":1,"message":"'$amountMsg' is never reassigned. Use 'const' instead.","line":14,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":14,"endColumn":13},{"ruleId":"prefer-const","severity":1,"message":"'threeDecimalCurrencies' is never reassigned. Use 'const' instead.","line":15,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":15,"endColumn":25},{"ruleId":"prefer-const","severity":1,"message":"'invalids' is never reassigned. Use 'const' instead.","line":86,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":86,"endColumn":11},{"ruleId":"prefer-const","severity":1,"message":"'rules' is never reassigned. Use 'const' instead.","line":87,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":87,"endColumn":8},{"ruleId":"no-shadow","severity":1,"message":"'value' is already declared in the upper scope on line 82 column 6.","line":105,"column":27,"nodeType":"Identifier","messageId":"noShadow","endLine":105,"endColumn":32},{"ruleId":"mediawiki/msg-doc","severity":1,"message":"All possible message keys should be documented. See https://w.wiki/4r9a for details.","line":107,"column":14,"nodeType":"CallExpression","endLine":107,"endColumn":64},{"ruleId":"no-shadow","severity":1,"message":"'i' is already declared in the upper scope on line 85 column 3.","line":113,"column":23,"nodeType":"Identifier","messageId":"noShadow","endLine":113,"endColumn":24},{"ruleId":"prefer-const","severity":1,"message":"'countryField' is never reassigned. Use 'const' instead.","line":145,"column":2,"nodeType":"Identifier","messageId":"useConst","endLine":145,"endColumn":14},{"ruleId":"prefer-const","severity":1,"message":"'emailAdd' is never reassigned. Use 'const' instead.","line":168,"column":2,"nodeType":"Identifier","messageId":"useConst","endLine":168,"endColumn":10},{"ruleId":"prefer-const","severity":1,"message":"'phoneAdd' is never reassigned. Use 'const' instead.","line":220,"column":2,"nodeType":"Identifier","messageId":"useConst","endLine":220,"endColumn":10},{"ruleId":"mediawiki/no-cookie","severity":1,"message":"Avoid direct access to document.cookie. Use mw.cookie instead.","line":241,"column":11,"nodeType":"Identifier","messageId":"noCookie","endLine":241,"endColumn":17},{"ruleId":"mediawiki/no-cookie","severity":1,"message":"Avoid direct access to document.cookie. Use mw.cookie instead.","line":242,"column":16,"nodeType":"Identifier","messageId":"noCookie","endLine":242,"endColumn":22},{"ruleId":"mediawiki/no-cookie","severity":1,"message":"Avoid direct access to document.cookie. Use mw.cookie instead.","line":243,"column":12,"nodeType":"Identifier","messageId":"noCookie","endLine":243,"endColumn":18}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":16,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/**\n * Validate the donation amount to make sure it is formatted correctly and at least a minimum amount.\n * TODO: also validate ceiling\n */\nwindow.validateAmount = function () {\n\tlet error = true,\n\t\tamount = $( 'input[name=\"amount\"]' ).val(), // get the amount\n\t\tcurrency = '',\n\t\trates = mw.config.get( 'wgDonationInterfaceCurrencyRates' ),\n\t\tamountRules = mw.config.get( 'wgDonationInterfaceAmountRules' ),\n\t\tminimumInDonationCurrency,\n\t\tminDisplay,\n\t\tmessage = mediaWiki.msg( 'donate_interface-smallamount-error' ),\n\t\t$amountMsg = $( '#amountMsg' ),\n\t\tthreeDecimalCurrencies = [ 'BHD', 'CLF', 'IQD', 'JOD', 'KWD', 'LYD',\n\t\t\t'MGA', 'MRO', 'OMR', 'TND' ];\n\t// Check amount is at least the minimum\n\tif ( $( 'input[name=\"currency\"]' ).length ) {\n\t\tcurrency = $( 'input[name=\"currency\"]' ).val();\n\t}\n\tif ( $( 'select[name=\"currency\"]' ).length ) {\n\t\tcurrency = $( 'select[name=\"currency\"]' ).val();\n\t}\n\n\t// Normalize weird amount formats.\n\t// Don't mess with these unless you know what you're doing.\n\t/*jshint ignore:start*/\n\tamount = amount.replace( /[,.](\\d)$/, '\\:$10' );\n\tamount = amount.replace( /[,.](\\d)(\\d)$/, '\\:$1$2' );\n\tif ( threeDecimalCurrencies.includes( currency ) ) {\n\t\tamount = amount.replace( /[,.](\\d)(\\d)(\\d)$/, '\\:$1$2$3' );\n\t}\n\tamount = amount.replace( /[,.]/g, '' );\n\tamount = amount.replace( /:/, '.' );\n\t$( 'input[name=\"amount\"]' ).val( amount ); // set the new amount back into the form\n\t/*jshint ignore:end*/\n\n\t// Check amount is a real number, sets error as true (good) if no issues\n\terror = ( amount === null || isNaN( amount ) || amount.value <= 0 );\n\n\tif ( currency === amountRules.currency || ( typeof rates[ currency ] ) === 'undefined' ) {\n\t\tminimumInDonationCurrency = amountRules.min;\n\t} else {\n\t\t// Rates are all relative to USD, so we divide the configured minimum by its corresponding\n\t\t// rate to get the minimum in USD, then multiply by the rate of the donation currency to get\n\t\t// the minimum in the donation currency.\n\t\tminimumInDonationCurrency = amountRules.min / rates[ amountRules.currency ] * rates[ currency ];\n\t}\n\t// if we're on a new form, clear existing amount error\n\t$amountMsg.removeClass( 'errorMsg' ).addClass( 'errorMsgHide' ).text( '' );\n\tif ( ( amount < minimumInDonationCurrency ) || error ) {\n\t\t// Round to two decimal places (TODO: no decimals for some currencies)\n\t\tminDisplay = Math.round( minimumInDonationCurrency * 100 ) / 100;\n\t\tmessage = message.replace( '$1', minDisplay + ' ' + currency );\n\t\t$amountMsg.removeClass( 'errorMsgHide' ).addClass( 'errorMsg' ).text( message );\n\n\t\terror = true;\n\t\t// See if we're on a webitects accordion form\n\t\tif ( $( '#step1wrapper' ).length ) {\n\t\t\t$( '#step1wrapper' ).slideDown();\n\t\t\t$( '#paymentContinue' ).show();\n\t\t\t// If we're on an Ingenico iframe form, slide up the 3rd step to force the user to\n\t\t\t// generate a new iframe after they change the form.\n\t\t\tif ( $( '#payment iframe' ).length ) {\n\t\t\t\t$( '#step3wrapper' ).slideUp();\n\t\t\t}\n\t\t}\n\t\t$( '#other-amount' ).val( '' );\n\t\t$( '#other-amount' ).focus();\n\t}\n\treturn !error;\n};\n\n/**\n * Validates the personal information fields\n * FIXME: Bad name, this validates more than just personal info.\n * Move the good parts to ext.donationInterface.validation.js\n *\n * @return {boolean} true if no errors, false otherwise (also uses in-page error messages to notify the user)\n */\nwindow.validate_personal = function () {\n\tlet value, countryField, emailAdd, phoneAdd, invalid, apos, dotpos, domain,\n\t\terrorsPresent = false,\n\t\t$formField,\n\t\ti,\n\t\tinvalids = [ '..', '/', '\\\\', ',', '<', '>' ],\n\t\trules = mediaWiki.config.get( 'wgDonationInterfaceValidationRules' ) || [];\n\n\tfunction clearError( field ) {\n\t\t$( '#' + field ).removeClass( 'errorHighlight' );\n\t\t$( '#' + field + 'Msg' )\n\t\t\t.removeClass( 'errorMsg' )\n\t\t\t.addClass( 'errorMsgHide' );\n\t}\n\n\tfunction setError( field, message ) {\n\t\terrorsPresent = true;\n\t\t$( '#' + field ).addClass( 'errorHighlight' );\n\t\t$( '#' + field + 'Msg' )\n\t\t\t.removeClass( 'errorMsgHide' )\n\t\t\t.addClass( 'errorMsg' )\n\t\t\t.text( message );\n\t}\n\n\tfunction isEmpty( field, value ) {\n\t\treturn !$.trim( value ) ||\n\t\t\tvalue === mediaWiki.msg( 'donate_interface-donor-' + field );\n\t}\n\n\t// Generically defined rules set by GatewayAdapter->getClientSideValidationRules\n\t$.each( rules, ( fieldKey, ruleList ) => {\n\t\tclearError( fieldKey );\n\t\t$.each( ruleList, ( i, rule ) => {\n\t\t\tlet failed = false;\n\t\t\t$formField = $( '#' + fieldKey );\n\t\t\tif ( $formField.length === 0 ) {\n\t\t\t\t// Radio button special case. First see if the group exists ...\n\t\t\t\t$formField = $( 'input[name=' + fieldKey + ']' );\n\t\t\t\tif ( $formField.length > 0 ) {\n\t\t\t\t\t// ... then filter to just the selected button\n\t\t\t\t\t$formField = $formField.filter( ':checked' );\n\t\t\t\t} else {\n\t\t\t\t\t// Field doesn't exist by id or by name\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvalue = $formField.val();\n\t\t\tif ( rule.required ) {\n\t\t\t\tif ( isEmpty( fieldKey, value ) ) {\n\t\t\t\t\tfailed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( rule.pattern && !isEmpty( fieldKey, value ) ) {\n\t\t\t\tif ( !value.match( new RegExp( rule.pattern ) ) ) {\n\t\t\t\t\tfailed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( failed ) {\n\t\t\t\tsetError( fieldKey, rule.message );\n\t\t\t}\n\t\t} );\n\t} );\n\n\t// FIXME: wouldn't $( '#country' ).val() work for both types?\n\tcountryField = document.getElementById( 'country' );\n\tif ( countryField && countryField.type === 'select-one' ) { // country is a dropdown select\n\t\tif ( !$.trim( countryField.options[ countryField.selectedIndex ].value ) ) {\n\t\t\tsetError(\n\t\t\t\t'country',\n\t\t\t\tmediaWiki.msg( 'donate_interface-error-msg-country' )\n\t\t\t);\n\t\t} else {\n\t\t\tclearError( 'country' );\n\t\t}\n\t} else { // country is a hidden or text input\n\t\tif ( !$.trim( countryField.value ) ) {\n\t\t\tsetError(\n\t\t\t\t'country',\n\t\t\t\tmediaWiki.msg( 'donate_interface-error-msg-country' )\n\t\t\t);\n\t\t} else {\n\t\t\tclearError( 'country' );\n\t\t}\n\t}\n\n\t// validate email address\n\t// FIXME: replace with regex in wgDonationInterfaceValidationRules\n\temailAdd = document.getElementById( 'email' );\n\tif (\n\t\temailAdd &&\n\t\t$.trim( emailAdd.value ) &&\n\t\temailAdd.value !== mediaWiki.msg( 'donate_interface-donor-email' )\n\t) {\n\t\tinvalid = false;\n\n        const specialCharacterRegex = [ '(^[\\\\-])|',\n        '([`!@#$%^&*()_+\\\\-=\\\\[\\\\]{};\\':\"\\\\\\\\|,.<>\\\\/?~]+$)' ];\n\n        if ( new RegExp( specialCharacterRegex.join( '' ) ).test( emailAdd.value ) ) {\n            setError(\n                'email',\n                mediaWiki.msg( 'donate_interface-error-msg-invalid-email' )\n            );\n            invalid = true;\n        }\n\t\tapos = emailAdd.value.indexOf( '@' );\n\t\tdotpos = emailAdd.value.lastIndexOf( '.' );\n\n\t\tif ( apos < 1 || dotpos - apos < 2 ) {\n\t\t\tsetError(\n\t\t\t\t'email',\n\t\t\t\tmediaWiki.msg( 'donate_interface-error-msg-invalid-email' )\n\t\t\t);\n\t\t\tinvalid = true;\n\t\t}\n\n\t\tdomain = emailAdd.value.slice( Math.max( 0, apos + 1 ) );\n\n\t\tfor ( i = 0; i < invalids.length && !invalid; i++ ) {\n\t\t\tif ( domain.includes( invalids[ i ] ) ) {\n\t\t\t\tsetError(\n\t\t\t\t\t'email',\n\t\t\t\t\tmediaWiki.msg( 'donate_interface-error-msg-invalid-email' )\n\t\t\t\t);\n\t\t\t\tinvalid = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( /[0-9]$/.test( domain ) ) {\n\t\t\tsetError(\n\t\t\t\t'email',\n\t\t\t\tmediaWiki.msg( 'donate_interface-error-msg-invalid-email' )\n\t\t\t);\n\t\t}\n\t}\n\n\t// Validate phone\n\t// US only to start T380106\n\tphoneAdd = document.getElementById( 'phone' );\n\tif (\n\t\tcountryField.value === 'US' &&\n\t\tphoneAdd &&\n\t\t$.trim( phoneAdd.value ) &&\n\t\tphoneAdd.value !== mediaWiki.msg( 'donate_interface-donor-phone' )\n\t) {\n\t\t// Phone a friend\n\t\tconst phoneRegexUS = /^(1[ \\-.]?)?(\\(?\\d{3}\\)?[ \\-.]?)(\\d{3})[ \\-.]?(\\d{4})$/;\n\n\t\tif ( !new RegExp( phoneRegexUS ).test( phoneAdd.value.trim() ) ) {\n\t\t\tsetError(\n\t\t\t\t'phone',\n\t\t\t\tmediaWiki.msg( 'donate_interface-error-msg-invalid-phone' )\n\t\t\t);\n\t\t} else {\n\t\t\tclearError( 'phone' );\n\t\t}\n\t}\n\n\t// Make sure cookies are enabled\n\tdocument.cookie = 'wmf_test=1;';\n\tif ( document.cookie.includes( 'wmf_test=1' ) ) {\n\t\tdocument.cookie = 'wmf_test=; expires=Thu, 01-Jan-70 00:00:01 GMT;'; // unset the cookie\n\t\tclearError( 'cookie' );\n\t} else {\n\t\terrorsPresent = true; // display error\n\t\tsetError( 'cookie', mediaWiki.msg( 'donate_interface-error-msg-cookies' ) );\n\t}\n\n\treturn !errorsPresent;\n};\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/package-lock.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/package.json","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"no-extra-parens","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/paypal_ec_gateway/forms/js/paypal.js","messages":[{"ruleId":"prefer-const","severity":1,"message":"'di' is never reassigned. Use 'const' instead.","line":2,"column":6,"nodeType":"Identifier","messageId":"useConst","endLine":2,"endColumn":8},{"ruleId":"prefer-const","severity":1,"message":"'rules' is never reassigned. Use 'const' instead.","line":3,"column":3,"nodeType":"Identifier","messageId":"useConst","endLine":3,"endColumn":8}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"( function ( $, mw ) {\n\tlet di = mw.donationInterface,\n\t\trules = mediaWiki.config.get( 'wgDonationInterfaceValidationRules' ) || [],\n\t\trulesSatisfied = false;\n\n\tfunction redirect( result ) {\n\t\t// We don't actually want to enable the form on redirect or in the\n\t\t// complete phase of callDonateApi, so we override enable here.\n\t\tdi.forms.enable = function () {};\n\t\tlocation.assign( result.redirect );\n\t}\n\n\tdi.forms.submit = function () {\n\t\t// MediaWiki uses the \"uselang\" parameter to set the language for localization\n\t\t// Checkout /payments/includes/api/ApiMain.php\n\t\tdi.forms.callDonateApi( redirect, { uselang: $( '#language' ).val() } );\n\t};\n\tif ( rules.length === 0 ) {\n\t\trulesSatisfied = true;\n\t} else {\n\t\t// TODO: refactor validation to separate out showing errors, and\n\t\t// check that all the rules are satisfied on page load without\n\t\t// showing errors.\n\t\tif ( di.forms.getOptIn() !== '' ) {\n\t\t\trulesSatisfied = true;\n\t\t}\n\t}\n\tif ( rulesSatisfied && !di.validation.hasErrors() ) {\n\t\tdi.forms.submit();\n\t}\n} )( jQuery, mediaWiki );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/app.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/contact_details.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/donations_history.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/donations_list_table.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/error-component.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/feedback-survey_component.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/greeting_component.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/header.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/onetime_contribution.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/popup_link.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-cancel-confirmation.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-cancel-form.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-cancel-option-container.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-cancel-success.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-pause-form.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-pause-success.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-update-form.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring-update-success.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring_contribution.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":57,"column":19,"nodeType":"MemberExpression","messageId":"forbidden","endLine":57,"endColumn":32},{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":71,"column":19,"nodeType":"MemberExpression","messageId":"forbidden","endLine":71,"endColumn":32},{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":88,"column":19,"nodeType":"MemberExpression","messageId":"forbidden","endLine":88,"endColumn":32}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach afterEach*/\nconst VueTestUtils = require( '@vue/test-utils' );\nconst RecurringContributionComponent = require( '../../../modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue' );\nconst { recurring: recurring_mock } = require( '../mocks/contribution_mock.mock.js' );\nconst { inactive_recurring: inactive_recurring_mock } = require( '../mocks/contribution_mock.mock.js' );\nconst { inactive_yearly_recurring: inactive_yearly_recurring_mock } = require( '../mocks/contribution_mock.mock.js' );\nconst { when } = require( 'jest-when' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\nconst entities = require( 'entities' );\n\ndescribe( 'Active recurring contribution test', () => {\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'newDonationUrl' ).mockReturnValue( 'http://donate.test' );\n\t} );\n\tit( 'Active recurring contribution renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.shallowMount( RecurringContributionComponent, {\n\t\t\tprops: {\n\t\t\t\tcontribution: recurring_mock,\n\t\t\t\tisActive: true\n\t\t\t}\n\t\t} );\n\n\t\tconst element = wrapper.find( '.is-recurring' );\n\t\texpect( element.exists() ).toBe( true );\n\t\texpect( element.html() ).toContain( recurring_mock.amount_frequency_key );\n\t\texpect( element.html() ).toContain( recurring_mock.amount_formatted );\n\t\texpect( element.html() ).toContain( recurring_mock.currency );\n\t\texpect( element.html() ).toContain( recurring_mock.payment_method );\n\t\texpect( element.html() ).toContain( recurring_mock.next_sched_contribution_date_formatted );\n\t\texpect( element.html() ).not.toContain( `<a href=\"#/cancel-donations/${ recurring_mock.id }\" class=\"link\"> donorportal-recurring-cancel </a>` );\n\t\texpect( element.html() ).not.toContain( `<a target=\"_self\" href=\"#/update-donations/${ recurring_mock.id }\"` );\n\t\texpect( element.html() ).not.toContain( `<a href=\"#/pause-donations/${ recurring_mock.id }\" class=\"link\"> donorportal-recurring-pause </a>` );\n\t} );\n\n\tit( 'Donor contact details component renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.shallowMount( RecurringContributionComponent, {\n\t\t\tprops: {\n\t\t\t\tcontribution: inactive_recurring_mock,\n\t\t\t\tisActive: false\n\t\t\t}\n\t\t} );\n\n\t\tconst element = wrapper.find( '.is-lapsed' );\n\t\texpect( element.exists() ).toBe( true );\n\t\texpect( element.html() ).toContain( 'donorportal-last-amount-and-date' );\n\t\texpect( element.html() ).toContain( inactive_recurring_mock.amount_formatted );\n\t\texpect( element.html() ).toContain( inactive_recurring_mock.currency );\n\t\texpect( element.html() ).not.toContain( inactive_recurring_mock.payment_method );\n\t\texpect( element.html() ).toContain( inactive_recurring_mock.last_contribution_date_formatted );\n\t\texpect( element.html() ).toContain( inactive_recurring_mock.restart_key );\n\t\texpect( element.html() ).toContain( '<a target=\"_blank\" href=\"http://donate.test' );\n\t} );\n\tit( 'Only adds last contribution if there if there is any on record', () => {\n\t\tconst wrapper = VueTestUtils.shallowMount( RecurringContributionComponent, {\n\t\t\tprops: {\n\t\t\t\tcontribution: Object.assign( inactive_recurring_mock, {\n\t\t\t\t\thasLastContribution: false\n\t\t\t\t} ),\n\t\t\t\tisActive: false\n\t\t\t}\n\t\t} );\n        const element = wrapper.find( '.is-lapsed' );\n        expect( element.exists() ).toBe( true );\n        expect( element.html() ).not.toContain( 'donorportal-last-amount-and-date' );\n        expect( entities.decodeHTML( element.html() ) ).toContain( '<a target=\"_blank\" href=\"http://donate.test/?preSelect=100&country=US&frequency=monthly' );\n    } );\n\tit( 'Render is processing status correctly', () => {\n\t\tconst wrapper = VueTestUtils.shallowMount( RecurringContributionComponent, {\n\t\t\tprops: {\n\t\t\t\tcontribution: Object.assign( recurring_mock, {\n\t\t\t\t\tis_processing: true\n\t\t\t\t} ),\n\t\t\t\tisActive: true\n\t\t\t}\n\t\t} );\n\n\t\tconst element = wrapper.find( '.is-processing' );\n\t\texpect( element.exists() ).toBe( true );\n\t\texpect( element.html() ).toContain( 'donorportal-processing' );\n\t\texpect( element.html() ).not.toContain( `<a href=\"#/cancel-donations/${ recurring_mock.id }\" class=\"link\"> donorportal-recurring-cancel </a>` );\n\t\texpect( element.html() ).not.toContain( `<a target=\"_self\" href=\"#/update-donations/${ recurring_mock.id }\"` );\n\t\texpect( element.html() ).not.toContain( `<a href=\"#/pause-donations/${ recurring_mock.id }\" class=\"link\"> donorportal-recurring-pause </a>` );\n\t} );\n\tit( 'Render correct new donation link', () => {\n\t\tconst wrapper = VueTestUtils.shallowMount( RecurringContributionComponent, {\n\t\t\tprops: {\n\t\t\t\tcontribution: Object.assign( inactive_yearly_recurring_mock, {\n\t\t\t\t\thasLastContribution: false\n\t\t\t\t} ),\n\t\t\t\tisActive: false\n\t\t\t}\n\t\t} );\n\t\tconst element = wrapper.find( '.is-lapsed' );\n\t\texpect( element.exists() ).toBe( true );\n\t\texpect( element.html() ).not.toContain( 'donorportal-last-amount-and-date' );\n\t\texpect( entities.decodeHTML( element.html() ) ).toContain( '<a target=\"_blank\" href=\"http://donate.test/?preSelect=150&country=BR&frequency=annual' );\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/components/recurring_contribution_summary.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/mocks/annual_donations_list.mock.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/mocks/contact_details.mock.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/mocks/contribution_mock.mock.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/mocks/donor_data.mock.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/mocks/endowment_donations_list.mock.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/routes/router.test.js","messages":[],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/amount-downgrade.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":5,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":5,"endColumn":47}],"suppressedMessages":[{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":38,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":38,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":78,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":78,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":182,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":182,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":223,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":223,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":262,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":262,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":301,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":301,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach afterEach jest */\n/* eslint-disable es-x/no-promise */\n\n// Mock vue router composables\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\nconst { useRoute } = require( 'vue-router' );\n\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\nconst DowngradeAmountView = require( '../../../modules/ext.donationInterface.donorPortal/views/AmountDowngrade.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\nconst { recurring: contribution_mock } = require( '../mocks/contribution_mock.mock.js' );\n\nconst RECURRING_UPDATE_API_ACTION = 'requestUpdateRecurring';\ndescribe( 'Downgrade donations view', () => {\n\twindow.alert = jest.fn();\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'recurringUpgradeMaxUSD' ).mockReturnValue( 1000000 );\n\t\twhen( global.mw.config.get ).calledWith( 'wgDonationInterfaceCurrencyRates' ).mockReturnValue( [\n\t\t\t[ 'USD', 1 ],\n\t\t\t[ 'EUR', 0.9 ],\n\t\t\t[ 'GBP', 0.8 ]\n\t\t] );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Downgrade Donations view renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst updateDonationViewBody = wrapper.find( '#update-donations-form' );\n\t\texpect( updateDonationViewBody.exists() ).toBe( true );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-downgrade-recurring-heading' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-text' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-new-donation' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-change-mind' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-new-donation-effective-date' );\n\n\t\t// Ensure success text is not visible on first load\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the success view on success downgrade', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst updateDonationViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = updateDonationViewBody.find( '#new-recurring-amount' );\n\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.resolve( {\n\t\t\tresult: {\n\t\t\t\tmessage: 'Success',\n\t\t\t\tnext_sched_contribution_date: '2025-10-02 00:00:02'\n\t\t\t} } )\n\t\t);\n\t\tamountInput.element.value = 1;\n\t\tawait amountInput.trigger( 'input' );\n\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = updateDonationViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '1',\n\t\t\ttxn_type: 'recurring_downgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\t\texpect( successText.html() ).toContain( `donorportal-update-recurring-confirmation-text:[<strong>${ contribution_mock.currency_symbol + amountInput.element.value + ' ' + contribution_mock.currency }</strong>,<strong>${ contribution_mock.next_sched_contribution_date_formatted }</strong>]` );\n\t\texpect( successText.html() ).toContain( 'donorportal-update-recurring-confirmation-header' );\n\t\texpect( successText.html() ).toContain( 'donorportal-update-recurring-confirmation-header-subtitle' );\n\t\texpect( successText.html() ).toContain( 'donorportal-return-to-account-button' );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the no submit if amount the same', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tconst DowngradeAmountViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = DowngradeAmountViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 10;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = DowngradeAmountViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\t\texpect( window.alert ).toHaveBeenCalledWith( 'Please enter an amount different from your current donation.' );\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledTimes( 0 );\n\t} );\n\n\tit( 'Renders the no submit if amount outside of price range', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tprops: {\n\t\t\t\trecurringContribution: contribution_mock\n\t\t\t},\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tconst DowngradeAmountViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = DowngradeAmountViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 0.1;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = DowngradeAmountViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\t\texpect( window.alert ).toHaveBeenCalledWith( `Please enter a valid amount between 1 and ${ contribution_mock.amount }.` );\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledTimes( 0 );\n\t} );\n} );\n\ndescribe( 'Downgrade donations view errors', () => {\n\twindow.alert = jest.fn();\n\tconst email = 'help@example.com';\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( email );\n\t\twhen( global.mw.config.get ).calledWith( 'recurringUpgradeMaxUSD' ).mockReturnValue( 1000000 );\n\t\twhen( global.mw.config.get ).calledWith( 'wgDonationInterfaceCurrencyRates' ).mockReturnValue( [\n\t\t\t[ 'USD', 1 ],\n\t\t\t[ 'EUR', 0.9 ],\n\t\t\t[ 'GBP', 0.8 ]\n\t\t] );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst DowngradeAmountViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = DowngradeAmountViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = DowngradeAmountViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '3',\n\t\t\ttxn_type: 'recurring_downgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\t} );\n\n\tit( 'Renders the error view on session failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'no-session' )\n\t\t);\n\n\t\tconst DowngradeAmountViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = DowngradeAmountViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = DowngradeAmountViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '3',\n\t\t\ttxn_type: 'recurring_downgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-no-session' );\n\t} );\n\n\tit( 'Renders the error view on bad contact id failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'bad-contact-id' )\n\t\t);\n\n\t\tconst DowngradeAmountViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = DowngradeAmountViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = DowngradeAmountViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '3',\n\t\t\ttxn_type: 'recurring_downgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( `donorportal-error-bad-contact-id:[${ email }]` );\n\t} );\n\n\tit( 'Renders the error view on bad contribution recur id failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( DowngradeAmountView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'bad-contribution-recur-id' )\n\t\t);\n\n\t\tconst DowngradeAmountViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = DowngradeAmountViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = DowngradeAmountViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '3',\n\t\t\ttxn_type: 'recurring_downgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( `donorportal-error-bad-contribution-recur-id:[${ email }]` );\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/annual-conversion.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":5,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":5,"endColumn":47}],"suppressedMessages":[{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":38,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":38,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":82,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":82,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":142,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":142,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":205,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":205,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":246,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":246,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":285,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":285,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":324,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":324,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach afterEach jest */\n/* eslint-disable es-x/no-promise */\n\n// Mock vue router composables\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\nconst { useRoute } = require( 'vue-router' );\n\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\nconst AnnualConversionView = require( '../../../modules/ext.donationInterface.donorPortal/views/AnnualConversion.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\nconst { recurring: contribution_mock } = require( '../mocks/contribution_mock.mock.js' );\n\nconst ANNUAL_CONVERSION_API_ACTION = 'requestAnnualConversion';\ndescribe( 'Annual conversion view', () => {\n\twindow.alert = jest.fn();\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'recurringUpgradeMaxUSD' ).mockReturnValue( 1000000 );\n\t\twhen( global.mw.config.get ).calledWith( 'wgDonationInterfaceCurrencyRates' ).mockReturnValue( [\n\t\t\t[ 'USD', 1 ],\n\t\t\t[ 'EUR', 0.9 ],\n\t\t\t[ 'GBP', 0.8 ]\n\t\t] );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Annual Conversion view renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\texpect( AnnualConversionViewBody.exists() ).toBe( true );\n\t\texpect( AnnualConversionViewBody.html() ).toContain( 'donorportal-update-recurring-annual-convert-head' );\n\t\texpect( AnnualConversionViewBody.html() ).toContain( 'donorportal-update-recurring-annual-convert-description' );\n\t\texpect( AnnualConversionViewBody.html() ).toContain( 'donorportal-update-recurring-annual-convert-select-below' );\n\t\texpect( AnnualConversionViewBody.html() ).toContain( 'donorportal-update-recurring-annual-convert-yearly-other-amount' );\n\t\texpect( AnnualConversionViewBody.html() ).toContain( 'donorportal-cancel-recurring-quit-header' );\n\t\texpect( AnnualConversionViewBody.html() ).toContain( 'donorportal-return-to-account-button' );\n\n\t\t// Ensure success text is not visible on first load\n\t\tconst successText = wrapper.find( '#recurring-contribution-annual-conversion-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the success view on success annual conversion', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tprops: {\n\t\t\t\trecurringContribution: contribution_mock\n\t\t\t},\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.resolve( {\n\t\t\tresult: {\n\t\t\t\tmessage: 'Success'\n\t\t\t} } )\n\t\t);\n\t\tamountInput.element.value = 100;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: ANNUAL_CONVERSION_API_ACTION,\n\t\t\tamount: '100',\n\t\t\tnext_sched_contribution_date: contribution_mock.next_contribution_date_yearly,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-annual-conversion-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\t\texpect( successText.html() ).toContain( 'donorportal-thank-you' );\n\t\texpect( successText.html() ).toContain( 'donorportal-return-to-account-button' );\n\t\texpect( successText.html() ).toContain( 'donorportal-update-recurring-yearly-conversion-success' );\n\t\texpect( successText.html() ).toContain( `donorportal-update-recurring-yearly-conversion-on-schedule:[<strong>${ contribution_mock.next_contribution_date_yearly_formatted }</strong>]` );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the no submit if amount outside of price range', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\t\tamountInput.element.value = 0.1;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\t\texpect( window.alert ).toHaveBeenCalledWith( 'Please enter a valid amount between 1 and 1000000.' );\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledTimes( 0 );\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\t\tamountInput.element.value = 30;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: ANNUAL_CONVERSION_API_ACTION,\n\t\t\tamount: '30',\n\t\t\tnext_sched_contribution_date: contribution_mock.next_contribution_date_yearly,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-annual-conversion-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\n\t} );\n} );\n\ndescribe( 'Annual conversion view errors', () => {\n\twindow.alert = jest.fn();\n\tconst email = 'help@example.com';\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( email );\n\t\twhen( global.mw.config.get ).calledWith( 'recurringUpgradeMaxUSD' ).mockReturnValue( 1000000 );\n\t\twhen( global.mw.config.get ).calledWith( 'wgDonationInterfaceCurrencyRates' ).mockReturnValue( [\n\t\t\t[ 'USD', 1 ],\n\t\t\t[ 'EUR', 0.9 ],\n\t\t\t[ 'GBP', 0.8 ]\n\t\t] );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: ANNUAL_CONVERSION_API_ACTION,\n\t\t\tamount: '3',\n\t\t\tnext_sched_contribution_date: contribution_mock.next_contribution_date_yearly,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\t} );\n\n\tit( 'Renders the error view on session failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'no-session' )\n\t\t);\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: ANNUAL_CONVERSION_API_ACTION,\n\t\t\tamount: '3',\n\t\t\tnext_sched_contribution_date: contribution_mock.next_contribution_date_yearly,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-no-session' );\n\t} );\n\n\tit( 'Renders the error view on bad contact id failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'bad-contact-id' )\n\t\t);\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: ANNUAL_CONVERSION_API_ACTION,\n\t\t\tamount: '3',\n\t\t\tnext_sched_contribution_date: contribution_mock.next_contribution_date_yearly,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( `donorportal-error-bad-contact-id:[${ email }]` );\n\t} );\n\n\tit( 'Renders the error view on bad contribution recur id failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( AnnualConversionView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'bad-contribution-recur-id' )\n\t\t);\n\n\t\tconst AnnualConversionViewBody = wrapper.find( '#form-convert-yearly' );\n\t\tconst amountInput = AnnualConversionViewBody.find( '#new-annual-recurring-amount' );\n\t\tamountInput.element.value = 3;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = AnnualConversionViewBody.find( '#submit-annual-conversion' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: ANNUAL_CONVERSION_API_ACTION,\n\t\t\tamount: '3',\n\t\t\tnext_sched_contribution_date: contribution_mock.next_contribution_date_yearly,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tis_from_save_flow: false\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( `donorportal-error-bad-contribution-recur-id:[${ email }]` );\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/cancel-donations.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":5,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":5,"endColumn":47}],"suppressedMessages":[{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":32,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":32,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":341,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":341,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach afterEach jest */\n/* eslint-disable es-x/no-promise */\n\n// Mock vue router composables\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\nconst { useRoute } = require( 'vue-router' );\n\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\nconst CancelDonationsView = require( '../../../modules/ext.donationInterface.donorPortal/views/CancelDonations.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\n\nconst RECURRING_PAUSE_API_ACTION = 'requestPauseRecurring';\nconst RECURRING_CANCEL_API_ACTION = 'requestCancelRecurring';\ndescribe( 'Cancel donations view', () => {\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'emailPreferencesUrl' ).mockReturnValue( 'https://emailprefs.wiki' );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Pause Donations view renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\t\texpect( cancelDonationsViewBody.exists() ).toBe( true );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-cancel-recurring-other-ways-heading' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-cancel-recurring-other-ways-text' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-cancel-recurring-pause-alternative-header' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-cancel-recurring-pause-alternative-text' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-pause-recurring-pause-button' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain(\n\t\t\t'donorportal-cancel-recurring-frequency-annual-switch-alternative-header' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain(\n\t\t\t'donorportal-cancel-recurring-frequency-annual-switch-alternative-text' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain(\n\t\t\t'donorportal-cancel-recurring-frequency-annual-switch-alternative-button' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain(\n\t\t\t'donorportal-cancel-recurring-amount-change-alternative-header' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain(\n\t\t\t'donorportal-cancel-recurring-amount-change-alternative-text' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain(\n\t\t\t'donorportal-cancel-recurring-amount-change-alternative-button' );\n\n\t\t// Ensure duration option list are rendered and visible\n\t\tconst pauseDonationsOptionsList = wrapper.findAll( '#radio-button-options-list' );\n\t\texpect( pauseDonationsOptionsList.length ).toBe( 3 );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-pause-recurring-days:[30]' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-pause-recurring-days:[60]' );\n\t\texpect( cancelDonationsViewBody.html() ).toContain( 'donorportal-pause-recurring-days:[90]' );\n\n\t\t// Ensure pause recurring success text is not visible on first load\n\t\tconst pauseSuccessText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( pauseSuccessText.exists() ).toBe( false );\n\n\t\t// Ensure pause recurring failure text is not visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the pause recurring success view on success', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith( {\n\t\t\tduration: '60 Days',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: Number( DonorDataMock.recurringContributions[ 0 ].id ),\n\t\t\tnext_sched_contribution_date: DonorDataMock.recurringContributions[ 0 ].next_sched_contribution_date,\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tis_from_save_flow: true\n\t\t} ).mockResolvedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'Success',\n\t\t\t\t\tnext_sched_contribution_date: '2025-10-02 00:00:02'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst selectedPeriod = cancelDonationsViewBody.find( '#option-60days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst pauseRecurringOption = cancelDonationsViewBody.find( '#pause-recurring-alt' );\n\t\tconst pauseRecurringOptionButton = pauseRecurringOption.find( '#submit-pause-action' );\n\t\tawait pauseRecurringOptionButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\t\texpect( successText.html() ).toContain( '2025-10-02 00:00:02' );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the pause error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '90 Days',\n\t\t\tcontact_id: DonorDataMock.contact_id,\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: '123',\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02',\n\t\t\tis_from_save_flow: true\n\t\t} ).mockRejectedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'API error'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\tconst selectedPeriod = cancelDonationsViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst pauseRecurringOption = cancelDonationsViewBody.find( '#pause-recurring-alt' );\n\t\tconst pauseRecurringOptionButton = pauseRecurringOption.find( '#submit-pause-action' );\n\t\tawait pauseRecurringOptionButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-pause-failure' );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the cancel confirmation page and the recurring success view on successful cancel', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith( {\n\t\t\treason: 'Update',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: Number( DonorDataMock.recurringContributions[ 0 ].id ),\n\t\t\taction: RECURRING_CANCEL_API_ACTION\n\t\t} ).mockResolvedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'Success'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst proceedCancelButton = cancelDonationsViewBody.find( '#continue' );\n\t\tawait proceedCancelButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst cancelConfirmationScreen = wrapper.find( '#recurring-cancellation-confirmation' );\n\t\texpect( cancelConfirmationScreen.exists() ).toBe( true );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( 'donorportal-cancel-recurring-confirmation-request-header' );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( 'donorportal-cancel-recurring-confirmation-request-text' );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( DonorDataMock.recurringContributions[ 0 ].amount_frequency_key );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( DonorDataMock.recurringContributions[ 0 ].payment_method );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( 'donorportal-cancel-recurring-request-for-reason' );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( 'donorportal-cancel-recurring-cancel-button' );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( 'donorportal-cancel-recurring-changed-my-mind' );\n\t\texpect( cancelConfirmationScreen.html() ).toContain( 'donorportal-cancel-recurring-switch-to-annual' );\n\n\t\tconst givingMethodReason = cancelConfirmationScreen.find( '#option-giving-method' );\n\t\tawait givingMethodReason.trigger( 'input' );\n\n\t\tconst submitButton = cancelConfirmationScreen.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( true );\n\t\texpect( cancelSuccessText.html() ).toContain( `donorportal-cancel-monthly-recurring-confirmation-text:[<strong>${ DonorDataMock.recurringContributions[ 0 ].amount_frequency_key }:[${ DonorDataMock.recurringContributions[ 0 ].amount_formatted },${ DonorDataMock.recurringContributions[ 0 ].currency }]</strong>]` );\n\t} );\n\n\tit( 'Renders the cancel confirmation page and the recurring error view on failed cancel', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith(\n\t\t\texpect.anything()\n\t\t).mockRejectedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'API error'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst proceedCancelButton = cancelDonationsViewBody.find( '#continue' );\n\t\tawait proceedCancelButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst cancelConfirmationScreen = wrapper.find( '#recurring-cancellation-confirmation' );\n\t\tconst givingMethodReason = cancelConfirmationScreen.find( '#option-giving-method' );\n\t\tawait givingMethodReason.trigger( 'input' );\n\n\t\tconst submitButton = cancelConfirmationScreen.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure cancel recurring success text is not visible on failure\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\n\t\t// Ensure recurring failure text is visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\n\t} );\n\n\tit( 'Submits a tracking value from the URL', async () => {\n\t\twindow.history.pushState( {}, '', '/donorPortal?wmf_campaign=testCampaign' );\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith( {\n\t\t\tduration: '60 Days',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: Number( DonorDataMock.recurringContributions[ 0 ].id ),\n\t\t\tnext_sched_contribution_date: DonorDataMock.recurringContributions[ 0 ].next_sched_contribution_date,\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\twmf_campaign: 'testCampaign',\n\t\t\tis_from_save_flow: true\n\t\t} ).mockResolvedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'Success',\n\t\t\t\t\tnext_sched_contribution_date: '2025-10-02 00:00:02'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst selectedPeriod = cancelDonationsViewBody.find( '#option-60days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst pauseRecurringOption = cancelDonationsViewBody.find( '#pause-recurring-alt' );\n\t\tconst pauseRecurringOptionButton = pauseRecurringOption.find( '#submit-pause-action' );\n\t\tawait pauseRecurringOptionButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\t\twindow.history.back();\n\t} );\n} );\n\ndescribe( 'Cancel donations view errors', () => {\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'emailPreferencesUrl' ).mockReturnValue( 'https://emailprefs.wiki' );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Renders the pause error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith(\n\t\t\texpect.anything()\n\t\t).mockRejectedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'API error'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\tconst selectedPeriod = cancelDonationsViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst pauseRecurringOption = cancelDonationsViewBody.find( '#pause-recurring-alt' );\n\t\tconst pauseRecurringOptionButton = pauseRecurringOption.find( '#submit-pause-action' );\n\t\tawait pauseRecurringOptionButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-pause-failure' );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the pause error view on contact id failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith(\n\t\t\texpect.anything()\n\t\t).mockRejectedValueOnce( 'bad-contact-id' );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\tconst selectedPeriod = cancelDonationsViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst pauseRecurringOption = cancelDonationsViewBody.find( '#pause-recurring-alt' );\n\t\tconst pauseRecurringOptionButton = pauseRecurringOption.find( '#submit-pause-action' );\n\t\tawait pauseRecurringOptionButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-bad-contact-id:[help@example.com]' );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the cancel confirmation page and the recurring error view on failed cancel', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith(\n\t\t\texpect.anything()\n\t\t).mockRejectedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'API error'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst proceedCancelButton = cancelDonationsViewBody.find( '#continue' );\n\t\tawait proceedCancelButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst cancelConfirmationScreen = wrapper.find( '#recurring-cancellation-confirmation' );\n\n\t\tconst givingMethodReason = cancelConfirmationScreen.find( '#option-giving-method' );\n\t\tawait givingMethodReason.trigger( 'input' );\n\n\t\tconst submitButton = cancelConfirmationScreen.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure cancel recurring success text is not visible after failure\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\n\t\t// Ensure recurring failure text is visible after failure\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\n\t} );\n\n\tit( 'Renders the cancel confirmation page and the recurring error view on failed cancel due to recur id', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith( expect.anything() )\n\t\t\t.mockRejectedValueOnce( 'bad-contribution-recur-id' );\n\n\t\tconst proceedCancelButton = cancelDonationsViewBody.find( '#continue' );\n\t\tawait proceedCancelButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst cancelConfirmationScreen = wrapper.find( '#recurring-cancellation-confirmation' );\n\n\t\tconst givingMethodReason = cancelConfirmationScreen.find( '#option-giving-method' );\n\t\tawait givingMethodReason.trigger( 'input' );\n\n\t\tconst submitButton = cancelConfirmationScreen.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\n\t\t// Ensure recurring failure text is visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-bad-contribution-recur-id:[help@example.com]' );\n\n\t} );\n\n\tit( 'Renders the cancel confirmation page and the recurring error view on failed cancel', async () => {\n\t\tconst wrapper = VueTestUtils.mount( CancelDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst cancelDonationsViewBody = wrapper.find( '#cancel-donations-form' );\n\n\t\twhen( global.mw.Api.prototype.post ).calledWith(\n\t\t\texpect.anything()\n\t\t).mockRejectedValueOnce( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'API error'\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tconst proceedCancelButton = cancelDonationsViewBody.find( '#continue' );\n\t\tawait proceedCancelButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst cancelConfirmationScreen = wrapper.find( '#recurring-cancellation-confirmation' );\n\n\t\tconst givingMethodReason = cancelConfirmationScreen.find( '#option-giving-method' );\n\t\tawait givingMethodReason.trigger( 'input' );\n\n\t\tconst submitButton = cancelConfirmationScreen.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\t// Ensure pause success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure cancel recurring success text is not visible on first load\n\t\tconst cancelSuccessText = wrapper.find( '#recurring-contribution-cancel-success' );\n\t\texpect( cancelSuccessText.exists() ).toBe( false );\n\n\t\t// Ensure recurring failure text is visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/home.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":2,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":2,"endColumn":47}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global jest describe it expect beforeEach afterEach*/\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\n\nconst HomeView = require( '../../../modules/ext.donationInterface.donorPortal/views/Home.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\n\ndescribe( 'Home view', () => {\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'lorem@ipsum.co' );\n\t\twhen( global.mw.config.get ).calledWith( 'emailPreferencesUrl' ).mockReturnValue( 'https://emailprefs.wiki' );\n\t\twhen( global.mw.config.get ).calledWith( 'newDonationUrl' ).mockReturnValue( 'http://donate.test' );\n\t} );\n\n\tit( 'Home view renders the donor data from config', async () => {\n\t\tconst wrapper = VueTestUtils.mount( HomeView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ],\n\t\t\t\tmocks: {\n\t\t\t\t\t$route: {\n\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\t\t\t\t\tcontact_id: DonorDataMock.contact_id\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t\tconst element = wrapper.find( '.dp-dashboard' );\n\t\texpect( element.exists() ).toBe( true );\n\t\texpect( element.html() ).toContain( DonorDataMock.address.street_address );\n\t\texpect( element.html() ).toContain( DonorDataMock.address.city );\n\t\texpect( element.html() ).toContain( DonorDataMock.address.country );\n\t\texpect( element.html() ).toContain( DonorDataMock.name );\n\t\texpect( element.html() ).toContain( DonorDataMock.email );\n\t\texpect( element.html() ).toContain( DonorDataMock.donorID );\n\t\texpect( element.findAll( '.dp-card__appeal.is-recurring' ).length ).toBe( DonorDataMock.recurringContributions.length );\n\t\texpect( element.findAll( '.dp-card__appeal.is-lapsed' ).length ).toBe( DonorDataMock.inactiveRecurringContributions.length );\n\t\texpect( element.find( '.donorportal-recent-donation' ).exists ).not.toBe( true );\n\t\texpect( element.findAll( '.donorportal-donations-table-row' ).length ).toBe( DonorDataMock.annualFundContributions.length + DonorDataMock.endowmentContributions.length );\n\t} );\n\n\tit( 'Renders the most recent one time payment when no active or cancelled recurring is on record', async () => {\n\t\tconst summary = DonorDataMock;\n\t\tsummary.recurringContributions = [];\n\t\tsummary.inactiveRecurringContributions = [];\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( summary );\n\n\t\tconst wrapper = VueTestUtils.mount( HomeView, {\n\t\t\tglobal: {\n\t\t\t\tmocks: {\n\t\t\t\t\t$route: {\n\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\t\t\t\t\tcontact_id: DonorDataMock.contact_id\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tawait VueTestUtils.flushPromises();\n\n\t\tconst element = wrapper.find( '.dp-dashboard' );\n\t\texpect( element.exists() ).toBe( true );\n\t\texpect( element.html() ).toContain( DonorDataMock.address.street_address );\n\t\texpect( element.html() ).toContain( DonorDataMock.address.city );\n\t\texpect( element.html() ).toContain( DonorDataMock.address.country );\n\t\texpect( element.html() ).toContain( DonorDataMock.name );\n\t\texpect( element.html() ).toContain( DonorDataMock.email );\n\t\texpect( element.html() ).toContain( DonorDataMock.donorID );\n\t\texpect( element.findAll( '.donorportal-recurring-contribution' ).length ).toBe( 0 );\n\t\texpect( element.findAll( '.dp-card__appeal.is-recurring' ).length ).toBe( 0 );\n\t\texpect( element.find( '.donorportal-recent-donation' ).exists() ).toBe( true );\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/login.test.js","messages":[],"suppressedMessages":[{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":41,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":41,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":76,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":76,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":107,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":107,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":141,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":141,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/manage-donations.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":4,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":4,"endColumn":47}],"suppressedMessages":[],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach jest */\n\n// Mock vue router composables\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\nconst { useRoute } = require( 'vue-router' );\n\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\nconst ManageDonationsView = require( '../../../modules/ext.donationInterface.donorPortal/views/ManageDonations.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\n\ndescribe( 'Manage donations view', () => {\n    beforeEach( () => {\n        when( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n        when( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n        when( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n        when( global.mw.config.get ).calledWith( 'emailPreferencesUrl' ).mockReturnValue( 'https://emailprefs.wiki' );\n        useRoute.mockImplementation( () => ( {\n            params: {\n                id: '123'\n            }\n        } ) );\n    } );\n\n    it( 'Manage Donations view renders successfully', () => {\n        const wrapper = VueTestUtils.mount( ManageDonationsView, {\n            global: {\n                plugins: [ router ]\n            }\n        } );\n        const manageDonationViewBody = wrapper.find( '#manage-donations' );\n\n        expect( manageDonationViewBody.exists() ).toBe( true );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-heading' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-text' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-recurring-status-active' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-donor-card-heading' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-donor-card-text' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-heading' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-pause-gift' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-change-amount' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-cancel-recurring-frequency-annual-switch-alternative-button' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-cancel-gift' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-cancel-recurring-quit-header' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-return-to-account-button' );\n        expect( manageDonationViewBody.html() ).toContain( DonorDataMock.recurringContributions[ 0 ].payment_method );\n        expect( manageDonationViewBody.html() ).toContain( `donorportal-recurring-amount-monthly:[${ DonorDataMock.recurringContributions[ 0 ].amount_formatted },${ DonorDataMock.recurringContributions[ 0 ].currency }]` );\n        expect( manageDonationViewBody.html() ).toContain( `donorportal-recurring-next-amount-and-date:[${ DonorDataMock.recurringContributions[ 0 ].amount_formatted },${ DonorDataMock.recurringContributions[ 0 ].currency },${ DonorDataMock.recurringContributions[ 0 ].next_sched_contribution_date_formatted }]` );\n    } );\n\n    it( 'Manage Donations view renders successfully without conversion suggestion for yearly recurring', () => {\n        useRoute.mockImplementationOnce( () => ( {\n            params: {\n                id: '456'\n            }\n        } ) );\n        const wrapper = VueTestUtils.mount( ManageDonationsView, {\n            global: {\n                plugins: [ router ]\n            }\n        } );\n        const manageDonationViewBody = wrapper.find( '#manage-donations' );\n\n        expect( manageDonationViewBody.exists() ).toBe( true );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-heading' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-text' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-recurring-status-active' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-donor-card-heading' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-donor-card-text' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-heading' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-pause-gift' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-change-amount' );\n        expect( manageDonationViewBody.html() ).not.toContain( 'donorportal-cancel-recurring-frequency-annual-switch-alternative-button' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-manage-donation-management-cancel-gift' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-cancel-recurring-quit-header' );\n        expect( manageDonationViewBody.html() ).toContain( 'donorportal-return-to-account-button' );\n        expect( manageDonationViewBody.html() ).toContain( DonorDataMock.recurringContributions[ 1 ].payment_method );\n        expect( manageDonationViewBody.html() ).toContain( `donorportal-recurring-amount-annual:[${ DonorDataMock.recurringContributions[ 1 ].amount_formatted },${ DonorDataMock.recurringContributions[ 1 ].currency }]` );\n        expect( manageDonationViewBody.html() ).toContain( `donorportal-recurring-next-amount-and-date:[${ DonorDataMock.recurringContributions[ 1 ].amount_formatted },${ DonorDataMock.recurringContributions[ 1 ].currency },${ DonorDataMock.recurringContributions[ 1 ].next_sched_contribution_date_formatted }]` );\n    } );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/pause-donations.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":5,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":5,"endColumn":47}],"suppressedMessages":[{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":31,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":31,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":74,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":74,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":115,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":115,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":166,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":166,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":179,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":179,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":221,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":221,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":261,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":261,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":301,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":301,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach afterEach jest */\n/* eslint-disable es-x/no-promise */\n\n// Mock vue router composables\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\nconst { useRoute } = require( 'vue-router' );\n\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\nconst PauseDonationsView = require( '../../../modules/ext.donationInterface.donorPortal/views/PauseDonations.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\n\nconst RECURRING_PAUSE_API_ACTION = 'requestPauseRecurring';\ndescribe( 'Pause donations view', () => {\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'emailPreferencesUrl' ).mockReturnValue( 'https://emailprefs.wiki' );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Pause Donations view renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\texpect( pauseDonationViewBody.exists() ).toBe( true );\n\t\texpect( pauseDonationViewBody.html() ).toContain( 'donorportal-pause-recurring-heading' );\n\t\texpect( pauseDonationViewBody.html() ).toContain( 'donorportal-pause-recurring-subheading' );\n\t\texpect( pauseDonationViewBody.html() ).toContain( 'donorportal-pause-recurring-subtext' );\n\t\texpect( pauseDonationViewBody.html() ).toContain( 'donorportal-pause-recurring-specify-duration' );\n\t\texpect( pauseDonationViewBody.html() ).toContain( 'donorportal-pause-recurring-days' );\n\t\texpect( pauseDonationViewBody.html() ).toContain( 'donorportal-pause-recurring-pause-button' );\n\n\t\tconst pauseDonationsOptionsList = wrapper.findAll( '#radio-button-options-list' );\n\t\texpect( pauseDonationsOptionsList.length ).toBe( 3 );\n\n\t\t// Ensure success text is not visible on first load\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the success view on success', async () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\tconst selectedPeriod = pauseDonationViewBody.find( '#option-60days' );\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.resolve( {\n\t\t\t\tresult: {\n\t\t\t\t\tmessage: 'Success',\n\t\t\t\t\tnext_sched_contribution_date: '2025-10-02 00:00:02'\n\t\t\t\t}\n\t\t\t} )\n\t\t);\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = pauseDonationViewBody.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '60 Days',\n\t\t\tis_from_save_flow: false,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02'\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\t\texpect( successText.html() ).toContain( '2025-10-02 00:00:02' );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\tconst selectedPeriod = pauseDonationViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = pauseDonationViewBody.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '90 Days',\n\t\t\tis_from_save_flow: false,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02'\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-pause-failure' );\n\n\t} );\n} );\n\ndescribe( 'Pause donations view renders appropiate errors', () => {\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'emailPreferencesUrl' ).mockReturnValue( 'https://emailprefs.wiki' );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\tconst selectedPeriod = pauseDonationViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = pauseDonationViewBody.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '90 Days',\n\t\t\tis_from_save_flow: false,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02'\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-pause-failure' );\n\n\t} );\n\n\tit( 'Renders the error view on session failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'no-session' )\n\t\t);\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\tconst selectedPeriod = pauseDonationViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = pauseDonationViewBody.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '90 Days',\n\t\t\tis_from_save_flow: false,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02'\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-no-session' );\n\n\t} );\n\n\tit( 'Renders the error view on contact failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'bad-contact-id' )\n\t\t);\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\tconst selectedPeriod = pauseDonationViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = pauseDonationViewBody.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '90 Days',\n\t\t\tis_from_save_flow: false,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02'\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-bad-contact-id:[help@example.com]' );\n\n\t} );\n\n\tit( 'Renders the error view on contribution recur failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( PauseDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( 'bad-contribution-recur-id' )\n\t\t);\n\n\t\tconst pauseDonationViewBody = wrapper.find( '#pause-donations' );\n\t\tconst selectedPeriod = pauseDonationViewBody.find( '#option-90days' );\n\t\tselectedPeriod.element.selected = true;\n\t\tawait selectedPeriod.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = pauseDonationViewBody.find( '#continue' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_PAUSE_API_ACTION,\n\t\t\tduration: '90 Days',\n\t\t\tis_from_save_flow: false,\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123,\n\t\t\tnext_sched_contribution_date: '2025-08-02 00:00:02'\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-pause-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-bad-contribution-recur-id:[help@example.com]' );\n\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]},{"filePath":"/src/repo/tests/jest/views/update-donations.test.js","messages":[{"ruleId":"es-x/no-object-assign","severity":1,"message":"ES2015 'Object.assign' method is forbidden.","line":5,"column":34,"nodeType":"MemberExpression","messageId":"forbidden","endLine":5,"endColumn":47}],"suppressedMessages":[{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":38,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":38,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":81,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":81,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":193,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":193,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":249,"column":8,"nodeType":"Identifier","messageId":"forbidden","endLine":249,"endColumn":15,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":262,"column":10,"nodeType":"Identifier","messageId":"forbidden","endLine":262,"endColumn":17,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":302,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":302,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":339,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":339,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]},{"ruleId":"es-x/no-promise","severity":1,"message":"ES2015 'Promise' class is forbidden.","line":376,"column":58,"nodeType":"Identifier","messageId":"forbidden","endLine":376,"endColumn":65,"suppressions":[{"kind":"directive","justification":""}]}],"errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"/* global global describe it expect beforeEach afterEach jest */\n/* eslint-disable es-x/no-promise */\n\n// Mock vue router composables\njest.mock( 'vue-router', () => ( Object.assign( jest.requireActual( 'vue-router' ), { useRoute: jest.fn() } ) ) );\n\nconst VueTestUtils = require( '@vue/test-utils' );\nconst { when } = require( 'jest-when' );\nconst { useRoute } = require( 'vue-router' );\n\nconst router = require( '../../../modules/ext.donationInterface.donorPortal/router.js' );\nconst UpdateDonationsView = require( '../../../modules/ext.donationInterface.donorPortal/views/UpdateDonations.vue' );\nconst DonorDataMock = require( '../mocks/donor_data.mock.js' );\nconst { recurring: contribution_mock } = require( '../mocks/contribution_mock.mock.js' );\n\nconst RECURRING_UPDATE_API_ACTION = 'requestUpdateRecurring';\ndescribe( 'Update donations view', () => {\n\twindow.alert = jest.fn();\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'recurringUpgradeMaxUSD' ).mockReturnValue( 1000000 );\n\t\twhen( global.mw.config.get ).calledWith( 'wgDonationInterfaceCurrencyRates' ).mockReturnValue( [\n\t\t\t[ 'USD', 1 ],\n\t\t\t[ 'EUR', 0.9 ],\n\t\t\t[ 'GBP', 0.8 ]\n\t\t] );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Update Donations view renders successfully', () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst updateDonationViewBody = wrapper.find( '#update-donations-form' );\n\t\texpect( updateDonationViewBody.exists() ).toBe( true );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-heading' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-text' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-new-donation' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-change-mind' );\n\t\texpect( updateDonationViewBody.html() ).toContain( 'donorportal-update-recurring-new-donation-effective-date' );\n\n\t\t// Ensure success text is not visible on first load\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible on first load\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the success view on success downgrade', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tprops: {\n\t\t\t\trecurringContribution: contribution_mock\n\t\t\t},\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\n\t\tconst updateDonationViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = updateDonationViewBody.find( '#new-recurring-amount' );\n\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.resolve( {\n\t\t\tresult: {\n\t\t\t\tmessage: 'Success',\n\t\t\t\tnext_sched_contribution_date: '2025-10-02 00:00:02'\n\t\t\t} } )\n\t\t);\n\t\tamountInput.element.value = 1;\n\t\tawait amountInput.trigger( 'input' );\n\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = updateDonationViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '1',\n\t\t\ttxn_type: 'recurring_downgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\t\texpect( successText.html() ).toContain( `donorportal-update-recurring-confirmation-text:[<strong>${ contribution_mock.currency_symbol + amountInput.element.value + ' ' + contribution_mock.currency }</strong>,<strong>${ contribution_mock.next_sched_contribution_date_formatted }</strong>]` );\n\t\texpect( successText.html() ).toContain( 'donorportal-update-recurring-confirmation-header' );\n\t\texpect( successText.html() ).toContain( 'donorportal-update-recurring-confirmation-header-subtitle' );\n\t\texpect( successText.html() ).toContain( 'donorportal-return-to-account-button' );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the success view on success upgrade', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 90;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '90',\n\t\t\ttxn_type: 'recurring_upgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( true );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( false );\n\t} );\n\n\tit( 'Renders the no submit if amount the same', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 10;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\t\texpect( window.alert ).toHaveBeenCalledWith( 'Please enter an amount different from your current donation.' );\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledTimes( 0 );\n\t} );\n\n\tit( 'Renders the no submit if amount outside of price range', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 0.1;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\t\texpect( window.alert ).toHaveBeenCalledWith( 'Please enter a valid amount between 1 and 1000000.' );\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledTimes( 0 );\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 30;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '30',\n\t\t\ttxn_type: 'recurring_upgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\n\t} );\n} );\n\ndescribe( 'Update donations view failure', () => {\n\twindow.alert = jest.fn();\n\tbeforeEach( () => {\n\t\twhen( global.mw.config.get ).calledWith( 'donorData' ).mockReturnValue( DonorDataMock );\n\t\twhen( global.mw.config.get ).calledWith( 'requestDonorPortalPage' ).mockReturnValue( 'DonorPortal' );\n\t\twhen( global.mw.config.get ).calledWith( 'help_email' ).mockReturnValue( 'help@example.com' );\n\t\twhen( global.mw.config.get ).calledWith( 'recurringUpgradeMaxUSD' ).mockReturnValue( 1000000 );\n\t\twhen( global.mw.config.get ).calledWith( 'wgDonationInterfaceCurrencyRates' ).mockReturnValue( [\n\t\t\t[ 'USD', 1 ],\n\t\t\t[ 'EUR', 0.9 ],\n\t\t\t[ 'GBP', 0.8 ]\n\t\t] );\n\t\tuseRoute.mockImplementationOnce( () => ( {\n\t\t\tparams: {\n\t\t\t\tid: '123'\n\t\t\t}\n\t\t} ) );\n\t} );\n\n\tafterEach( () => {\n\t\tglobal.mw.Api.prototype.post.mockReturnValue(\n\t\t\tnew Promise( ( resolve, _ ) => {\n\t\t\t\tresolve( {} );\n\t\t\t} )\n\t\t);\n\t} );\n\n\tit( 'Renders the error view on failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation(\n\t\t\t() => Promise.reject( {\n\t\t\t\tmessage: 'API error'\n\t\t\t} )\n\t\t);\n\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 30;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '30',\n\t\t\ttxn_type: 'recurring_upgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-cancel-failure' );\n\n\t} );\n\n\tit( 'Renders the error view on session failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.reject( 'no-session' ) );\n\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 30;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '30',\n\t\t\ttxn_type: 'recurring_upgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-no-session' );\n\n\t} );\n\n\tit( 'Renders the error view on bad contact failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.reject( 'bad-contact-id' ) );\n\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 30;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '30',\n\t\t\ttxn_type: 'recurring_upgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-bad-contact-id:[help@example.com]' );\n\n\t} );\n\n\tit( 'Renders the error view on bad contact failure', async () => {\n\t\tconst wrapper = VueTestUtils.mount( UpdateDonationsView, {\n\t\t\tglobal: {\n\t\t\t\tplugins: [ router ]\n\t\t\t}\n\t\t} );\n\t\tglobal.mw.Api.prototype.post.mockImplementation( () => Promise.reject( 'bad-contribution-recur-id' ) );\n\n\t\tconst UpdateDonationsViewBody = wrapper.find( '#update-donations-form' );\n\t\tconst amountInput = UpdateDonationsViewBody.find( '#new-recurring-amount' );\n\t\tamountInput.element.value = 30;\n\t\tawait amountInput.trigger( 'input' );\n\t\tawait VueTestUtils.flushPromises();\n\t\tconst submitButton = UpdateDonationsViewBody.find( '#submit-update-action' );\n\t\tawait submitButton.trigger( 'click' );\n\t\tawait VueTestUtils.flushPromises();\n\n\t\texpect( global.mw.Api.prototype.post ).toHaveBeenCalledWith( {\n\t\t\taction: RECURRING_UPDATE_API_ACTION,\n\t\t\tamount: '30',\n\t\t\ttxn_type: 'recurring_upgrade',\n\t\t\tcontact_id: Number( DonorDataMock.contact_id ),\n\t\t\tchecksum: DonorDataMock.checksum,\n\t\t\tcontribution_recur_id: 123\n\t\t} );\n\n\t\t// Ensure success text is visible after successful API request\n\t\tconst successText = wrapper.find( '#recurring-contribution-update-success' );\n\t\texpect( successText.exists() ).toBe( false );\n\n\t\t// Ensure failure text is not visible after successful API request\n\t\tconst failureText = wrapper.find( '#error-component' );\n\t\texpect( failureText.exists() ).toBe( true );\n\t\texpect( failureText.html() ).toContain( 'donorportal-error-bad-contribution-recur-id:[help@example.com]' );\n\n\t} );\n} );\n","usedDeprecatedRules":[{"ruleId":"arrow-parens","replacedBy":[]},{"ruleId":"arrow-spacing","replacedBy":[]},{"ruleId":"lines-between-class-members","replacedBy":[]},{"ruleId":"no-new-require","replacedBy":[]},{"ruleId":"template-curly-spacing","replacedBy":[]},{"ruleId":"implicit-arrow-linebreak","replacedBy":[]},{"ruleId":"array-bracket-spacing","replacedBy":[]},{"ruleId":"block-spacing","replacedBy":[]},{"ruleId":"brace-style","replacedBy":[]},{"ruleId":"comma-dangle","replacedBy":[]},{"ruleId":"comma-style","replacedBy":[]},{"ruleId":"computed-property-spacing","replacedBy":[]},{"ruleId":"dot-location","replacedBy":[]},{"ruleId":"eol-last","replacedBy":[]},{"ruleId":"func-call-spacing","replacedBy":[]},{"ruleId":"key-spacing","replacedBy":[]},{"ruleId":"keyword-spacing","replacedBy":[]},{"ruleId":"linebreak-style","replacedBy":[]},{"ruleId":"max-statements-per-line","replacedBy":[]},{"ruleId":"new-parens","replacedBy":[]},{"ruleId":"no-floating-decimal","replacedBy":[]},{"ruleId":"no-multiple-empty-lines","replacedBy":[]},{"ruleId":"no-new-object","replacedBy":["no-object-constructor"]},{"ruleId":"no-tabs","replacedBy":[]},{"ruleId":"no-trailing-spaces","replacedBy":[]},{"ruleId":"no-whitespace-before-property","replacedBy":[]},{"ruleId":"object-curly-spacing","replacedBy":[]},{"ruleId":"operator-linebreak","replacedBy":[]},{"ruleId":"quote-props","replacedBy":[]},{"ruleId":"quotes","replacedBy":[]},{"ruleId":"semi","replacedBy":[]},{"ruleId":"semi-spacing","replacedBy":[]},{"ruleId":"semi-style","replacedBy":[]},{"ruleId":"space-before-blocks","replacedBy":[]},{"ruleId":"space-before-function-paren","replacedBy":[]},{"ruleId":"space-in-parens","replacedBy":[]},{"ruleId":"space-infix-ops","replacedBy":[]},{"ruleId":"space-unary-ops","replacedBy":[]},{"ruleId":"switch-colon-spacing","replacedBy":[]},{"ruleId":"no-extra-semi","replacedBy":[]},{"ruleId":"no-mixed-spaces-and-tabs","replacedBy":[]}]}]

--- end ---
$ /usr/bin/npm ci
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex-icons@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN deprecated osenv@0.1.5: This package is no longer supported.
npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated abab@2.0.6: Use your platform's native atob() and btoa() methods instead
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported
npm WARN deprecated domexception@4.0.0: Use your platform's native DOMException instead
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
npm WARN deprecated core-js@2.6.12: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
--- stdout ---

added 1115 packages, and audited 1116 packages in 14s

160 packages are looking for funding
  run `npm fund` for details

10 vulnerabilities (4 low, 2 high, 4 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ /usr/bin/npm test
--- stderr ---
PASS tests/jest/views/annual-conversion.test.js (5.858 s)
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <AnnualConversionView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <AnnualConversionView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/update-donations.test.js (5.961 s)
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/cancel-donations.test.js (6.037 s)
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "TypeError: Cannot read properties of undefined (reading 'next_sched_contribution_date')", got Error  
        at <ErrorComponent key=5 error-code= TypeError: Cannot read properties of undefined (reading 'next_sched_contribution_date')
          at next_sched_contribution_date (/src/repo/modules/ext.donationInterface.donorPortal/views/CancelDonations.vue:59:55) fallback-message-key="donorportal-pause-failure" > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=3 error-code= { result: { message: 'API error' } } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=5 error-code= { result: { message: 'API error' } } fallback-message-key="donorportal-pause-failure" > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=3 error-code= { result: { message: 'API error' } } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=3 error-code= { result: { message: 'API error' } } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/login.test.js
PASS tests/jest/views/amount-downgrade.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <AmountDowngradeView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/components/donations_list_table.test.js
PASS tests/jest/components/recurring_contribution.test.js
PASS tests/jest/views/pause-donations.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } fallback-message-key="donorportal-pause-failure" > 
        at <PauseDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } fallback-message-key="donorportal-pause-failure" > 
        at <PauseDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/manage-donations.test.js
PASS tests/jest/components/recurring-cancel-form.test.js
PASS tests/jest/components/recurring-cancel-confirmation.test.js
PASS tests/jest/views/home.test.js
PASS tests/jest/components/recurring_contribution_summary.test.js
PASS tests/jest/components/donations_history.test.js
PASS tests/jest/components/recurring-update-form.test.js
PASS tests/jest/components/recurring-pause-form.test.js
PASS tests/jest/components/header.test.js
PASS tests/jest/components/app.test.js
PASS tests/jest/components/recurring-cancel-success.test.js
PASS tests/jest/routes/router.test.js
PASS tests/jest/components/popup_link.test.js
PASS tests/jest/components/recurring-update-success.test.js
PASS tests/jest/components/contact_details.test.js
PASS tests/jest/components/recurring-cancel-option-container.test.js
PASS tests/jest/components/onetime_contribution.test.js
PASS tests/jest/components/recurring-pause-success.test.js
PASS tests/jest/components/greeting_component.test.js
PASS tests/jest/components/feedback-survey_component.test.js
PASS tests/jest/components/error-component.test.js

Test Suites: 29 passed, 29 total
Tests:       102 passed, 102 total
Snapshots:   0 total
Time:        12.18 s
Ran all test suites.
--- stdout ---

> test
> grunt test && npm run test:unit

Running "eslint:all" (eslint) task

/src/repo/Gruntfile.js
  37:11  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/adyen_gateway/forms/adyen.js
    1:26  warning  'Promise' is already defined as a built-in global variable           no-redeclare
    5:3   warning  'configFromServer' is never reassigned. Use 'const' instead          prefer-const
    6:3   warning  'payment_method' is never reassigned. Use 'const' instead            prefer-const
    8:3   warning  'country' is never reassigned. Use 'const' instead                   prefer-const
    9:3   warning  'language' is never reassigned. Use 'const' instead                  prefer-const
   17:3   warning  'GOOGLEPAY_COMPONENT_TYPE' is never reassigned. Use 'const' instead  prefer-const
   18:3   warning  'ACH_GET_DONOR_ADDRESS' is never reassigned. Use 'const' instead     prefer-const
   25:1   warning  Missing JSDoc @return type                                           jsdoc/require-returns-type
   66:5   warning  Unexpected var, use let or const instead                             no-var
   82:23  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
   84:11  warning  'bContact' is never reassigned. Use 'const' instead                  prefer-const
   85:8   warning  'sContact' is never reassigned. Use 'const' instead                  prefer-const
  133:5   warning  Unexpected var, use let or const instead                             no-var
  164:23  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  223:34  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  227:14  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  313:2   warning  'submitPromise' is never reassigned. Use 'const' instead             prefer-const
  313:22  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  401:6   warning  ES2015 'Object.assign' method is forbidden                           es-x/no-object-assign
  540:4   warning  ES2015 'Object.assign' method is forbidden                           es-x/no-object-assign
  550:4   warning  'containerName' is never reassigned. Use 'const' instead             prefer-const
  554:3   warning  'component_type' is never reassigned. Use 'const' instead            prefer-const
  573:3   warning  'oldShowErrors' is never reassigned. Use 'const' instead             prefer-const
  595:3   warning  'config' is never reassigned. Use 'const' instead                    prefer-const
  603:3   warning  'checkoutPromise' is never reassigned. Use 'const' instead           prefer-const
  627:4   warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  654:4   warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise

/src/repo/amazon_gateway/amazon.js
    3:6   warning  'clientId' is never reassigned. Use 'const' instead                   prefer-const
    4:3   warning  'sellerId' is never reassigned. Use 'const' instead                   prefer-const
    5:3   warning  'sandbox' is never reassigned. Use 'const' instead                    prefer-const
    6:3   warning  'returnUrl' is never reassigned. Use 'const' instead                  prefer-const
    7:3   warning  'widgetScript' is never reassigned. Use 'const' instead               prefer-const
    8:3   warning  'loginScript' is never reassigned. Use 'const' instead                prefer-const
    9:3   warning  'failPage' is never reassigned. Use 'const' instead                   prefer-const
   10:3   warning  'isRecurring' is never reassigned. Use 'const' instead                prefer-const
   14:3   warning  'validTokenPattern' is never reassigned. Use 'const' instead          prefer-const
   14:23  warning  Use a regular expression literal instead of the 'RegExp' constructor  prefer-regex-literals
   22:3   warning  'CARD_SELECT_DELAY' is never reassigned. Use 'const' instead          prefer-const
   98:2   warning  'accessToken' is never reassigned. Use 'const' instead                prefer-const
   99:2   warning  'loginError' is never reassigned. Use 'const' instead                 prefer-const
  129:12  warning  Avoid direct access to document.cookie. Use mw.cookie instead         mediawiki/no-cookie
  268:8   warning  Selector extensions are not allowed                                   no-jquery/no-sizzle

/src/repo/braintree_gateway/forms/braintree.js
  10:6  warning  'di' is never reassigned. Use 'const' instead              prefer-const
  12:3  warning  'payment_method' is never reassigned. Use 'const' instead  prefer-const
  13:3  warning  'scripts' is never reassigned. Use 'const' instead         prefer-const

/src/repo/dlocal_gateway/forms/dlocal.js
  27:7  warning  'dlocalInstance' is never reassigned. Use 'const' instead   prefer-const
  28:4  warning  'fields' is never reassigned. Use 'const' instead           prefer-const
  33:4  warning  'commonStyle' is never reassigned. Use 'const' instead      prefer-const
  49:3  warning  'cardField' is never reassigned. Use 'const' instead        prefer-const
  55:3  warning  'expirationField' is never reassigned. Use 'const' instead  prefer-const
  61:3  warning  'cvvField' is never reassigned. Use 'const' instead         prefer-const

/src/repo/gravy_gateway/forms/gravy.js
  454:43  warning  'appleSession' is already declared in the upper scope on line 14 column 3  no-shadow

/src/repo/modules/ext.donationInterface.donorPortal/ApiUtils.js
  13:16  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsDisclaimerComponent.vue
  4:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  6:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsHistory.vue
  128:25  warning  'panel' is already declared in the upper scope on line 138 column 10  no-shadow

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsListTable.vue
  21:22  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  41:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionForm.vue
   35:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
   55:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  100:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionSuccess.vue
  13:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  15:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelSuccess.vue
  13:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue
  33:29  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseSuccess.vue
  13:31  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateSuccess.vue
  15:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/views/LoginView.vue
   8:6   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  37:7   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  66:8   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  76:17  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/iframe.liberator.js
  1:10  warning  'self' is already defined as a built-in global variable  no-redeclare

/src/repo/modules/js/ext.donationInterface.applePayHelper.js
  4:1  warning  Missing JSDoc @param "$" type   jsdoc/require-param-type
  5:1  warning  Missing JSDoc @param "mw" type  jsdoc/require-param-type

/src/repo/modules/js/ext.donationInterface.employerAutoComplete.js
  28:21  warning  Prefer .then to .done  no-jquery/no-done-fail

/src/repo/modules/js/ext.donationInterface.errorLog.js
  16:3  warning  'postdata' is never reassigned. Use 'const' instead  prefer-const

/src/repo/modules/js/ext.donationInterface.forms.js
    4:1   warning  Missing JSDoc @param "$" type                        jsdoc/require-param-type
    5:1   warning  Missing JSDoc @param "mw" type                       jsdoc/require-param-type
   74:27  warning  Selector extensions are not allowed                  no-jquery/no-sizzle
   90:12  warning  '$element' is never reassigned. Use 'const' instead  prefer-const
  107:1   warning  Missing JSDoc @param "checkboxName" type             jsdoc/require-param-type
  111:12  warning  '$element' is never reassigned. Use 'const' instead  prefer-const
  126:1   warning  The type 'result' is undefined                       jsdoc/no-undefined-types
  148:3   warning  'sendData' is never reassigned. Use 'const' instead  prefer-const
  187:4   warning  ES2015 'Object.assign' method is forbidden           es-x/no-object-assign
  239:14  warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  269:10  warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  283:4   warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  321:10  warning  Selector extensions are not allowed                  no-jquery/no-sizzle
  325:30  warning  Selector extensions are not allowed                  no-jquery/no-sizzle

/src/repo/modules/js/ext.donationInterface.jaVariant02.js
  8:1  warning  Missing JSDoc @param "mw" type  jsdoc/require-param-type
  9:1  warning  Missing JSDoc @param "$" type   jsdoc/require-param-type

/src/repo/modules/js/ext.donationInterface.monthlyConvert.js
    2:6   warning  'mc' is never reassigned. Use 'const' instead                         prefer-const
    6:3   warning  'tyUrl' is never reassigned. Use 'const' instead                      prefer-const
    9:3   warning  'convertAmounts' is never reassigned. Use 'const' instead             prefer-const
   17:3   warning  'numAmounts' is never reassigned. Use 'const' instead                 prefer-const
   37:49  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
   78:39  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
  147:51  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
  148:7   warning  'rates' is never reassigned. Use 'const' instead                      prefer-const
  149:4   warning  'amountRules' is never reassigned. Use 'const' instead                prefer-const
  151:4   warning  '$smallAmountMessage' is never reassigned. Use 'const' instead        prefer-const
  161:3   warning  'formattedMin' is never reassigned. Use 'const' instead               prefer-const
  177:4   warning  'locale' is never reassigned. Use 'const' instead                     prefer-const
  180:3   warning  'presetAmount' is never reassigned. Use 'const' instead               prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvertAnnual.js
   3:7   warning  'mc' is never reassigned. Use 'const' instead                        prefer-const
   3:31  warning  'originalGetSendData' is never reassigned. Use 'const' instead       prefer-const
   4:4   warning  'originalAmount' is never reassigned. Use 'const' instead            prefer-const
   5:4   warning  '$otherAmountMonthlyInput' is never reassigned. Use 'const' instead  prefer-const
   5:62  warning  '$otherAmountAnnualInput' is never reassigned. Use 'const' instead   prefer-const
   6:4   warning  '$otherMonthlySubmit' is never reassigned. Use 'const' instead       prefer-const
   6:60  warning  '$otherAnnualSubmit' is never reassigned. Use 'const' instead        prefer-const
   7:4   warning  '$smallAmountMessage' is never reassigned. Use 'const' instead       prefer-const
  15:3   warning  'originalAmountFormatted' is never reassigned. Use 'const' instead   prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvertMultiplier.js
  3:7  warning  'mc' is never reassigned. Use 'const' instead              prefer-const
  4:3  warning  'originalAmount' is never reassigned. Use 'const' instead  prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvert_011.js
  3:7  warning  'mc' is never reassigned. Use 'const' instead              prefer-const
  4:4  warning  'locale' is never reassigned. Use 'const' instead          prefer-const
  5:3  warning  'originalAmount' is never reassigned. Use 'const' instead  prefer-const
  6:3  warning  'currency' is never reassigned. Use 'const' instead        prefer-const
  7:3  warning  'presetAmount' is never reassigned. Use 'const' instead    prefer-const
  8:3  warning  'formattedAsk' is never reassigned. Use 'const' instead    prefer-const

/src/repo/modules/js/ext.donationInterface.recurUpgrade.js
   3:7  warning  '$submitButton' is never reassigned. Use 'const' instead      prefer-const
   4:4  warning  '$amountField' is never reassigned. Use 'const' instead       prefer-const
   5:4  warning  '$otherAmountField' is never reassigned. Use 'const' instead  prefer-const
   6:4  warning  '$totalMessage' is never reassigned. Use 'const' instead      prefer-const
   7:4  warning  '$newTotalAmount' is never reassigned. Use 'const' instead    prefer-const
   8:4  warning  '$form' is never reassigned. Use 'const' instead              prefer-const
   9:4  warning  'originalAmount' is never reassigned. Use 'const' instead     prefer-const
  10:4  warning  'currency' is never reassigned. Use 'const' instead           prefer-const
  11:4  warning  'maximum' is never reassigned. Use 'const' instead            prefer-const
  12:4  warning  'nextDateFormatted' is never reassigned. Use 'const' instead  prefer-const
  14:4  warning  'preSelectAmount' is never reassigned. Use 'const' instead    prefer-const
  38:4  warning  'valueIsValid' is never reassigned. Use 'const' instead       prefer-const

/src/repo/modules/js/ext.donationInterface.validation.js
   7:1   warning  Missing JSDoc @param "$" type                                      jsdoc/require-param-type
   8:1   warning  Missing JSDoc @param "mw" type                                     jsdoc/require-param-type
  11:6   warning  'di' is never reassigned. Use 'const' instead                      prefer-const
  13:3   warning  'mcDomains' is never reassigned. Use 'const' instead               prefer-const
  33:3   warning  'multiCountrySubdomains' is never reassigned. Use 'const' instead  prefer-const
  34:3   warning  'countryTlds' is never reassigned. Use 'const' instead             prefer-const
  40:26  warning  'i' is already declared in the upper scope on line 39 column 36    no-shadow

/src/repo/modules/validate_input.js
    1:1   warning  Missing JSDoc @return declaration                                                    jsdoc/require-returns
    9:3   warning  'rates' is never reassigned. Use 'const' instead                                     prefer-const
   10:3   warning  'amountRules' is never reassigned. Use 'const' instead                               prefer-const
   14:3   warning  '$amountMsg' is never reassigned. Use 'const' instead                                prefer-const
   15:3   warning  'threeDecimalCurrencies' is never reassigned. Use 'const' instead                    prefer-const
   86:3   warning  'invalids' is never reassigned. Use 'const' instead                                  prefer-const
   87:3   warning  'rules' is never reassigned. Use 'const' instead                                     prefer-const
  105:27  warning  'value' is already declared in the upper scope on line 82 column 6                   no-shadow
  107:14  warning  All possible message keys should be documented. See https://w.wiki/4r9a for details  mediawiki/msg-doc
  113:23  warning  'i' is already declared in the upper scope on line 85 column 3                       no-shadow
  145:2   warning  'countryField' is never reassigned. Use 'const' instead                              prefer-const
  168:2   warning  'emailAdd' is never reassigned. Use 'const' instead                                  prefer-const
  220:2   warning  'phoneAdd' is never reassigned. Use 'const' instead                                  prefer-const
  241:11  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie
  242:16  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie
  243:12  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie

/src/repo/paypal_ec_gateway/forms/js/paypal.js
  2:6  warning  'di' is never reassigned. Use 'const' instead     prefer-const
  3:3  warning  'rules' is never reassigned. Use 'const' instead  prefer-const

/src/repo/tests/jest/components/recurring_contribution.test.js
  57:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign
  71:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign
  88:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/amount-downgrade.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/annual-conversion.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/cancel-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/home.test.js
  2:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/manage-donations.test.js
  4:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/pause-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/update-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

✖ 170 problems (0 errors, 170 warnings)


Running "stylelint:all" (stylelint) task
>> Linted 17 files without errors

Running "banana:DonationInterface" (banana) task
>> The "fr" translation has 1 translation with trailing whitespace:
>> * donorportal-coming-soon
>> 10 message directories checked.

Done.

> test:unit
> jest

----------------------------------------------------|---------|----------|---------|---------|-----------------------
File                                                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s     
----------------------------------------------------|---------|----------|---------|---------|-----------------------
All files                                           |   94.33 |    85.48 |   88.02 |    94.3 |                       
 ext.donationInterface.donorPortal                  |   77.38 |    63.63 |   86.66 |   77.38 |                       
  ApiUtils.js                                       |   93.75 |       50 |     100 |   93.75 | 41                    
  normalizeInput.js                                 |   63.88 |    59.45 |      75 |   63.88 | 4,21,32-35,54-66      
  router.js                                         |   80.76 |    71.42 |      50 |   80.76 | 13-14,20-21,54        
  trackingParams.js                                 |     100 |      100 |     100 |     100 |                       
 ext.donationInterface.donorPortal/components       |   95.13 |    90.65 |   84.77 |   95.13 |                       
  App.vue                                           |     100 |      100 |     100 |     100 |                       
  DonationsDisclaimerComponent.vue                  |     100 |      100 |     100 |     100 |                       
  DonationsHistory.vue                              |   94.44 |      100 |      75 |   94.44 | 16-23                 
  DonationsListTable.vue                            |   89.28 |    94.44 |   73.33 |   89.28 | 23,40,137-153,183-199 
  DonorCardComponent.vue                            |     100 |       90 |     100 |     100 | 78                    
  DonorContactDetails.vue                           |   93.93 |    86.36 |     100 |   93.93 | 46,48                 
  EndowmentInformationComponent.vue                 |     100 |      100 |     100 |     100 |                       
  ErrorComponent.vue                                |     100 |      100 |     100 |     100 |                       
  FeedbackSurveyComponent.vue                       |     100 |      100 |     100 |     100 |                       
  GreetingComponent.vue                             |     100 |      100 |     100 |     100 |                       
  Header.vue                                        |   87.17 |    88.23 |   66.66 |   87.17 | 30-37,134             
  OnetimeContribution.vue                           |     100 |      100 |     100 |     100 |                       
  PopupLink.vue                                     |     100 |      100 |     100 |     100 |                       
  RadioButtonInput.vue                              |   94.44 |      100 |      75 |   94.44 | 63                    
  RecurringContributionAnnualConversionForm.vue     |   93.02 |    78.04 |      70 |   93.02 | 19,50,217-245,262     
  RecurringContributionAnnualConversionSuccess.vue  |      96 |      100 |   83.33 |      96 | 17                    
  RecurringContributionCancelAltOptionContainer.vue |     100 |      100 |   83.33 |     100 |                       
  RecurringContributionCancelConfirmation.vue       |   97.22 |       90 |      90 |   97.22 | 22                    
  RecurringContributionCancelForm.vue               |   94.23 |    91.66 |   85.71 |   94.23 | 24,52,55              
  RecurringContributionCancelSuccess.vue            |   96.42 |       50 |     100 |   96.42 | 28                    
  RecurringContributionComponent.vue                |   89.23 |    88.88 |   88.88 |   89.23 | 42-45,51,56,184       
  RecurringContributionPauseForm.vue                |   97.14 |      100 |    87.5 |   97.14 | 22                    
  RecurringContributionPauseSuccess.vue             |   94.44 |      100 |      75 |   94.44 | 17                    
  RecurringContributionSummary.vue                  |     100 |      100 |     100 |     100 |                       
  RecurringContributionUpdateForm.vue               |   96.72 |    89.18 |   83.33 |   96.72 | 85,183                
  RecurringContributionUpdateSuccess.vue            |     100 |      100 |     100 |     100 |                       
  RelatedContentComponent.vue                       |   94.11 |      100 |      60 |   94.11 | 102-108               
 ext.donationInterface.donorPortal/views            |   96.31 |    81.66 |   97.22 |   96.25 |                       
  AmountDowngrade.vue                               |   97.61 |       70 |     100 |   97.56 | 31                    
  AnnualConversion.vue                              |    97.5 |       70 |     100 |   97.43 | 32                    
  CancelDonations.vue                               |   98.38 |    77.77 |     100 |   98.36 | 35                    
  Home.vue                                          |   96.77 |       90 |     100 |   96.77 | 38                    
  LoginView.vue                                     |      90 |    89.47 |   90.47 |      90 | 36-38,60-62,94,207    
  ManageDonations.vue                               |   98.07 |    91.66 |     100 |   98.03 | 21                    
  PauseDonations.vue                                |   97.61 |       70 |     100 |   97.56 | 29                    
  UpdateDonations.vue                               |   97.56 |       75 |     100 |    97.5 | 30                    
----------------------------------------------------|---------|----------|---------|---------|-----------------------

--- end ---
Upgrading c:mediawiki/mediawiki-codesniffer from 50.0.0 -> 51.0.0
$ /usr/bin/composer update
--- stderr ---
Loading composer repositories with package information
                                                      Updating dependencies
Lock file operations: 0 installs, 3 updates, 0 removals
  - Upgrading composer/spdx-licenses (1.5.10 => 1.6.0)
  - Upgrading mediawiki/mediawiki-codesniffer (v50.0.0 => v51.0.0)
  - Upgrading phpcsstandards/phpcsextra (1.4.0 => 1.5.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 3 updates, 0 removals
    0 [>---------------------------]    0 [->--------------------------]
  - Upgrading phpcsstandards/phpcsextra (1.4.0 => 1.5.0): Extracting archive
  - Upgrading composer/spdx-licenses (1.5.10 => 1.6.0): Extracting archive
  - Upgrading mediawiki/mediawiki-codesniffer (v50.0.0 => v51.0.0): Extracting archive
 0/3 [>---------------------------]   0%
 3/3 [============================] 100%
Generating optimized autoload files
31 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
--- stdout ---

--- end ---
Previously failing phpcs rules: {'MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment', 'MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName', 'MediaWiki.Files.ClassMatchesFilename.NotMatch', 'PSR12.Properties.ConstantVisibility.NotFound', 'Squiz.Classes.ValidClassName.NotCamelCaps'}
$ vendor/bin/phpcs --report=json
--- stdout ---
{"totals":{"errors":105,"warnings":161,"fixable":0},"files":{"\/src\/repo\/dlocal_gateway\/dlocal_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DlocalGatewayResult' does not match filename 'dlocal_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/dlocal_gateway\/dlocal_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'BraintreeGatewayResult' does not match filename 'braintree_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/gateway_common\/LogPrefixProvider.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/paypal_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ResponseProcessingException.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/Simple3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/DonationInterface.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/PayPalCountry.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":7,"column":23},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":8,"column":23}]},"\/src\/repo\/paypal_ec_gateway\/paypal_express_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'PaypalExpressGatewayResult' does not match filename 'paypal_express_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/gateway_common\/DonorFullName.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PayPalAmount.php":{"errors":1,"warnings":0,"messages":[{"message":"Method name \"is_fractional_currency\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":11,"column":19}]},"\/src\/repo\/gateway_common\/RecurringConversion.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/PaypalExpressReturnUrl.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonorLanguage.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/FallbackLogPrefixer.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationLogProcessor.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/paypal_express_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'PaypalExpressGateway' does not match filename 'paypal_express_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/gateway_common\/CurrencyCountryRule.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ReturnUrl.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/UnstagingHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ErrorState.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonorLocale.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationLoggerFactory.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StagingHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ConfigurationReader.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DlocalGateway' does not match filename 'dlocal_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":13,"column":1}]},"\/src\/repo\/modules\/CurrencyRatesModule.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/email_forms\/EmailForm.php":{"errors":0,"warnings":1,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5}]},"\/src\/repo\/gateway_common\/ContributionTrackingPlusUnique.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":17,"column":75}]},"\/src\/repo\/email_forms\/RequestNewChecksumLinkTrait.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/employerSearch.api.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'EmployerSearchAPI' does not match filename 'employerSearch.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":17,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":32,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":37,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":42,"column":5}]},"\/src\/repo\/includes\/FraudFilters\/PreAuthorizeFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/SmsOptin.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/amazon_gateway\/amazon.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AmazonBillingApi' does not match filename 'amazon.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/extras\/extras.body.php":{"errors":4,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras' does not match filename 'extras.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":7,"column":10},{"message":"Class name \"Gateway_Extras\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":7,"column":16},{"message":"Method name \"generate_hash\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":59,"column":15},{"message":"Method name \"compare_hash\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":70,"column":15}]},"\/src\/repo\/includes\/DonorPortal\/ActivityTrackingTrait.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/FiscalNumber.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/GatewayType.php":{"errors":3,"warnings":0,"messages":[{"message":"Method name \"getData_Unstaged_Escaped\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":92,"column":12},{"message":"Method name \"session_ensure\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":198,"column":12},{"message":"Method name \"token_getSaltedSessionToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":240,"column":12}]},"\/src\/repo\/gateway_common\/WmfFramework.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":25,"column":30}]},"\/src\/repo\/extras\/conversion_log\/conversion_log.body.php":{"errors":3,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras_ConversionLog' does not match filename 'conversion_log.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":5,"column":1},{"message":"Class name \"Gateway_Extras_ConversionLog\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":5,"column":7},{"message":"Method name \"post_process\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":14,"column":15}]},"\/src\/repo\/includes\/Api\/ApiDonationClientError.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/AmountInCents.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestCancelRecurring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/amazon_gateway\/amazon_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AmazonGateway' does not match filename 'amazon_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":20,"column":1}]},"\/src\/repo\/amazon_gateway\/amazon_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/RecurringConversionTrait.php":{"errors":4,"warnings":0,"messages":[{"message":"Method name \"session_getData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":13,"column":21},{"message":"Method name \"session_resetForNewAttempt\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":19,"column":21},{"message":"Method name \"session_setDonorBackupData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":22,"column":21},{"message":"Method name \"session_MoveDonorDataToBackupForRecurringConversion\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":110,"column":12}]},"\/src\/repo\/gateway_common\/Amount.php":{"errors":2,"warnings":0,"messages":[{"message":"Method name \"is_fractional_currency\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":156,"column":19},{"message":"Method name \"is_exponent3_currency\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":174,"column":19}]},"\/src\/repo\/extras\/FraudFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/DonationInterface.class.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DonationInterface' does not match filename 'DonationInterface.class.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":7,"column":1}]},"\/src\/repo\/gateway_common\/ArrayHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/FraudFilters\/VelocityFilterRunner.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationApiBase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ValidationHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/Gravy3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/gravy_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestLogout.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/Frictionless3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PaymentResult.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StreetNumberValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StreetAddressValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/maintenance\/TestCrash.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationProfiler.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/RecurUpgrade\/Validator.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestPauseRecurring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PostalCodeValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRecurUpgradeClientError.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationInterfaceApiTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseDlocalTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree.adapter.php":{"errors":1,"warnings":6,"messages":[{"message":"Class name 'BraintreeAdapter' does not match filename 'braintree.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":14,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":17,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":18,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":19,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":51,"column":78},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":56,"column":55},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":57,"column":74}]},"\/src\/repo\/includes\/FraudFilters\/GenericVelocityFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseAdyenCheckoutTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/Abstract3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'BraintreeDonationApi' does not match filename 'braintree.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/gateway_common\/EmployerFieldValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/ArrayHelperTest.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":104,"column":36}]},"\/src\/repo\/gateway_common\/PaymentTransactionResponse.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseGravyTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/DonorPortal\/Hooks.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/IngenicoLocale.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/CiviproxyConnectTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ResultPages.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":104,"column":18}]},"\/src\/repo\/includes\/Api\/ApiRequestAnnualConversion.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/RecurringConversion.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'RecurringConversionApi' does not match filename 'RecurringConversion.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":5,"column":1}]},"\/src\/repo\/paypal_ec_gateway\/paypal_express.adapter.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'PaypalExpressAdapter' does not match filename 'paypal_express.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":24,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":25,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":26,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":27,"column":5}]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/TestingGenericAdapter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/TestingGatewayPage.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/MinFraudTestTrait.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/ingenico_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'IngenicoGateway' does not match filename 'ingenico_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":24,"column":1}]},"\/src\/repo\/gateway_common\/LocalClusterPsr6Cache.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/test_request\/test.request.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'TestingRequest' does not match filename 'test.request.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":27,"column":1}]},"\/src\/repo\/tests\/phpunit\/IntegrationTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/donation.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DonationApi' does not match filename 'donation.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":11,"column":1}]},"\/src\/repo\/ingenico_gateway\/IngenicoFormVariant.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/ingenico.adapter.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'IngenicoAdapter' does not match filename 'ingenico.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":16,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":19,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":20,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":21,"column":5}]},"\/src\/repo\/includes\/Api\/ApiRequestNewChecksumLink.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/TestingDonationLogger.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/IngenicoLocaleTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/IngenicoReturnUrlHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/ingenico_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'IngenicoGatewayResult' does not match filename 'ingenico_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/RealTimeBankTransferIdealTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationMessageTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'BraintreeGateway' does not match filename 'braintree_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":11,"column":1}]},"\/src\/repo\/ingenico_gateway\/ingenico_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/gravy_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyGateway' does not match filename 'gravy_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":10,"column":1}]},"\/src\/repo\/ingenico_gateway\/Ingenico3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenDonationApi' does not match filename 'adyen.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/special\/PaymentSettings.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/gravy_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyGatewayResult' does not match filename 'gravy_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/adyen_gateway\/adyen_apple.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenAppleApi' does not match filename 'adyen_apple.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":10,"column":1}]},"\/src\/repo\/extras\/custom_filters\/custom_filters.body.php":{"errors":2,"warnings":3,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters' does not match filename 'custom_filters.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":9,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":9,"column":7},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":12,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":48,"column":50}]},"\/src\/repo\/gateway_common\/DataValidator.php":{"errors":13,"warnings":1,"messages":[{"message":"Method name \"validate_email\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":238,"column":22},{"message":"Method name \"validate_currency_code\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":244,"column":22},{"message":"Method name \"validate_boolean\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":258,"column":22},{"message":"Method name \"validate_numeric\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":278,"column":22},{"message":"Method name \"validate_gateway\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":293,"column":22},{"message":"Method name \"validate_not_empty\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":307,"column":22},{"message":"Method name \"validate_not_just_punctuation\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":319,"column":19},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":320,"column":48},{"message":"Method name \"validate_name\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":335,"column":19},{"message":"Method name \"validate_address\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":345,"column":19},{"message":"Method name \"special_characters_in_wrong_locations\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":363,"column":19},{"message":"Method name \"cc_number_exists_in_str\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":386,"column":19},{"message":"Method name \"luhn_check\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":449,"column":19},{"message":"Method name \"ip_is_listed\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":505,"column":19}]},"\/src\/repo\/gateway_common\/ClientSideValidationHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal.adapter.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'DlocalAdapter' does not match filename 'dlocal.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":17,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":23,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":28,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":33,"column":5}]},"\/src\/repo\/gravy_gateway\/gravy.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyDonationApi' does not match filename 'gravy.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/gateway_common\/PaymentMethod.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_forms\/MustacheHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/GatewayPageTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DataValidatorTest.php":{"errors":0,"warnings":7,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":102,"column":34},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":103,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":104,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":106,"column":47},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":107,"column":51},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":118,"column":46},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":124,"column":33}]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/TestingPaypalExpressAdapter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/BlankAddressFields.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DlocalDonationApi' does not match filename 'dlocal.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/includes\/Api\/ApiRecurringModifyBase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/FraudFilters\/GenericPatternFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestUpdateRecurring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/EndowmentHooks.php":{"errors":0,"warnings":1,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":11,"column":5}]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/test.adapter.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'TTestingAdapter' does not match filename 'test.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":20,"column":1}]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/TestingDlocalAdapter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/RecurringTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/gravy_apple.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyAppleApi' does not match filename 'gravy_apple.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":10,"column":1}]},"\/src\/repo\/extras\/custom_filters\/filters\/source\/source.body.php":{"errors":2,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_Source' does not match filename 'source.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_Source\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":3,"column":7}]},"\/src\/repo\/includes\/FraudFilters\/PatternFilterRunner.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/RecurUpgrade.php":{"errors":0,"warnings":5,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":16,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":17,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":18,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":20,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":23,"column":5}]},"\/src\/repo\/tests\/phpunit\/GatewayValidationTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_forms\/MustacheErrorForm.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/minfraud\/minfraud.body.php":{"errors":2,"warnings":3,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_MinFraud' does not match filename 'minfraud.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":44,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_MinFraud\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":44,"column":7},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":272,"column":47},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":280,"column":16},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":288,"column":50}]},"\/src\/repo\/tests\/phpunit\/MustacheFormTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiClientErrorBase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/FundraiserMaintenance.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenFormLoadTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/LoggingTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/PaypalTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen_get_payment_methods.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenGetPaymentMethodsApi' does not match filename 'adyen_get_payment_methods.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":8,"column":1}]},"\/src\/repo\/adyen_gateway\/adyen_checkout_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenCheckoutGatewayResult' does not match filename 'adyen_checkout_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/extras\/civiproxy\/CiviproxyConnect.php":{"errors":0,"warnings":2,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":12,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":13,"column":5}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Amazon\/AmazonApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/functions\/functions.body.php":{"errors":2,"warnings":1,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_Functions' does not match filename 'functions.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_Functions\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":3,"column":7},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":53,"column":29}]},"\/src\/repo\/gateway_common\/ResultSwitcher.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/EmailPreferencesTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/CountryValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseIngenicoTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/amazon_gateway\/amazon.adapter.php":{"errors":1,"warnings":8,"messages":[{"message":"Class name 'AmazonAdapter' does not match filename 'amazon.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":34,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":36,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":37,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":38,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":227,"column":73},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":312,"column":36},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":314,"column":41},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":366,"column":36},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":370,"column":41}]},"\/src\/repo\/includes\/Validation\/AmountHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/referrer\/referrer.body.php":{"errors":2,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_Referrer' does not match filename 'referrer.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_Referrer\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":3,"column":7}]},"\/src\/repo\/adyen_gateway\/adyen_checkout_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenCheckoutGateway' does not match filename 'adyen_checkout_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":12,"column":1}]},"\/src\/repo\/tests\/phpunit\/AmountTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_forms\/includes\/Subdivisions.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/GatewayChooser.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":151,"column":41}]},"\/src\/repo\/gateway_common\/GatewayPage.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":374,"column":18}]},"\/src\/repo\/gateway_common\/PlaceholderFiscalNumber.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":13,"column":31},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":14,"column":31}]},"\/src\/repo\/gateway_common\/messages\/MessagesEs_419.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/SystemStatus.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/SecureFieldsCardTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/unit\/RecurUpgrade\/ValidatorTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/session_velocity\/session_velocity.body.php":{"errors":2,"warnings":5,"messages":[{"message":"Class name 'Gateway_Extras_SessionVelocityFilter' does not match filename 'session_velocity.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":18,"column":1},{"message":"Class name \"Gateway_Extras_SessionVelocityFilter\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":18,"column":7},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":33,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":34,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":35,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":36,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":37,"column":5}]},"\/src\/repo\/extras\/custom_filters\/filters\/ip_velocity\/ip_velocity.body.php":{"errors":2,"warnings":1,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_IP_Velocity' does not match filename 'ip_velocity.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_IP_Velocity\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":6,"column":7},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":110,"column":66}]},"\/src\/repo\/gateway_common\/StreetAddress.php":{"errors":2,"warnings":2,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":6,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":7,"column":5},{"message":"Method name \"stage_street\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":26,"column":15},{"message":"Method name \"stage_postal_code\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":48,"column":15}]},"\/src\/repo\/adyen_gateway\/adyen_submit_payment.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenSubmitPaymentApi' does not match filename 'adyen_submit_payment.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":11,"column":1}]},"\/src\/repo\/adyen_gateway\/adyen_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/EncryptedCardParameters.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Dlocal\/CardPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/ApplePayTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_forms\/Mustache.php":{"errors":2,"warnings":1,"messages":[{"message":"Class name 'Gateway_Form_Mustache' does not match filename 'Mustache.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":13,"column":1},{"message":"Class name \"Gateway_Form_Mustache\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":13,"column":7},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Amazon\/AmazonTest.php":{"errors":0,"warnings":5,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":134,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":164,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":191,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":216,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":245,"column":63}]},"\/src\/repo\/adyen_gateway\/adyen_checkout.adapter.php":{"errors":1,"warnings":1,"messages":[{"message":"Class name 'AdyenCheckoutAdapter' does not match filename 'adyen_checkout.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":13,"column":1},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":276,"column":25}]},"\/src\/repo\/gateway_forms\/Form.php":{"errors":2,"warnings":0,"messages":[{"message":"Class name 'Gateway_Form' does not match filename 'Form.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":5,"column":10},{"message":"Class name \"Gateway_Form\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":5,"column":16}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/CheckoutIdealTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/.phan\/config.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/GravyFormLoadTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationData.php":{"errors":0,"warnings":21,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":60,"column":30},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":69,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":70,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":73,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":74,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":79,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":84,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":103,"column":31},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":107,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":122,"column":29},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":125,"column":26},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":126,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":131,"column":26},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":134,"column":29},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":139,"column":22},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":367,"column":41},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":395,"column":72},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":400,"column":50},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":406,"column":34},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":407,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":584,"column":28}]},"\/src\/repo\/gravy_gateway\/gravy.adapter.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyAdapter' does not match filename 'gravy.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":22,"column":1}]},"\/src\/repo\/gateway_common\/MediaWikiLogHandler.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonorEmail.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/PlaceholderPhoneNumber.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Dlocal\/CashPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/GatewayAdapterTest.php":{"errors":1,"warnings":5,"messages":[{"message":"Method name \"TestSetValidationAction\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":538,"column":12},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":566,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":600,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":616,"column":61},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":634,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":665,"column":39}]},"\/src\/repo\/tests\/phpunit\/BaseBraintreeTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/EmailPreferences.php":{"errors":0,"warnings":5,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":13,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":14,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":18,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":20,"column":5}]},"\/src\/repo\/gateway_common\/MessageUtils.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenSubmitApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/GooglePayTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/EmployerSearchApiTest.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":116,"column":49}]},"\/src\/repo\/tests\/phpunit\/DonorLocaleTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/RedirectFormTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationDataTest.php":{"errors":0,"warnings":11,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":86,"column":91},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":146,"column":59},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":194,"column":91},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":241,"column":102},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":261,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":270,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":280,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":290,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":301,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":329,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":342,"column":98}]},"\/src\/repo\/tests\/phpunit\/IPVelocityTest.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":144,"column":64},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":209,"column":64}]},"\/src\/repo\/tests\/phpunit\/DonationInterfaceTestCase.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":176,"column":23},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":682,"column":51}]},"\/src\/repo\/tests\/phpunit\/FraudFiltersTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/LintYaml.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationQueueTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/PayPal\/PayPalExpressTest.php":{"errors":0,"warnings":6,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":120,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":210,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":355,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":967,"column":45},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1030,"column":45},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1066,"column":45}]},"\/src\/repo\/tests\/phpunit\/TestConfiguration.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":160,"column":34},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":161,"column":57}]},"\/src\/repo\/tests\/phpunit\/Adapter\/PayPal\/PayPalApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/DonorPortal.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":161,"column":28}]},"\/src\/repo\/tests\/phpunit\/GatewayChooserTest.php":{"errors":0,"warnings":5,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":235,"column":131},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":236,"column":131},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":237,"column":127},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":513,"column":76},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":546,"column":67}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/IngenicoTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Braintree\/PaypalPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Braintree\/VenmoPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/CheckoutCardTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenRecurringTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenGetPaymentMethodsApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/IngenicoApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/ResultSwitcherTest.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":59,"column":33}]},"\/src\/repo\/gateway_common\/gateway.adapter.php":{"errors":19,"warnings":24,"messages":[{"message":"Class name 'GatewayAdapter' does not match filename 'gateway.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":40,"column":10},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":44,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":45,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":184,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":185,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":186,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":186,"column":48},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":187,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":188,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":226,"column":41},{"message":"Method name \"getData_Staged\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":488,"column":15},{"message":"Method name \"getData_Unstaged_Escaped\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":581,"column":12},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1099,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1482,"column":61},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1503,"column":59},{"message":"Method name \"session_ensure\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2143,"column":12},{"message":"Method name \"session_getData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2154,"column":12},{"message":"Method name \"session_hasDonorData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2175,"column":12},{"message":"Method name \"session_setDonorBackupData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2184,"column":12},{"message":"Method name \"session_unsetDonorData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2193,"column":12},{"message":"Method name \"session_addDonorData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2203,"column":12},{"message":"Method name \"session_killAllEverything\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2221,"column":12},{"message":"Method name \"session_unsetAllData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2233,"column":12},{"message":"Method name \"session_resetForNewAttempt\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2249,"column":12},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2267,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2272,"column":28},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2280,"column":40},{"message":"Method name \"session_resetOnSwitch\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2315,"column":15},{"message":"Method name \"token_applyMD5AndSalt\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2390,"column":22},{"message":"Method name \"token_generateToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2408,"column":19},{"message":"Method name \"token_getSaltedSessionToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2413,"column":12},{"message":"Method name \"token_refreshAllTokenEverything\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2435,"column":15},{"message":"Method name \"token_matchEditToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2455,"column":15},{"message":"Method name \"token_checkTokens\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2480,"column":15},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2481,"column":31},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2520,"column":64},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2618,"column":106},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2676,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2690,"column":59},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2743,"column":45},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2744,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2885,"column":27},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2898,"column":27}]},"\/src\/repo\/gateway_common\/IsoDate.php":{"errors":0,"warnings":0,"messages":[]}}}

--- end ---
PHPCS run failed
$ vendor/bin/phpcs --report=json
--- stdout ---
{"totals":{"errors":105,"warnings":161,"fixable":0},"files":{"\/src\/repo\/braintree_gateway\/braintree_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'BraintreeGatewayResult' does not match filename 'braintree_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/braintree_gateway\/braintree_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/paypal_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DlocalGatewayResult' does not match filename 'dlocal_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/dlocal_gateway\/dlocal_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/PayPalCountry.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":7,"column":23},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":8,"column":23}]},"\/src\/repo\/paypal_ec_gateway\/paypal_express_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'PaypalExpressGatewayResult' does not match filename 'paypal_express_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/gateway_common\/LogPrefixProvider.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/DonationInterface.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonorFullName.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/Simple3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonorLanguage.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ResponseProcessingException.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/FallbackLogPrefixer.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/PaypalExpressReturnUrl.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/paypal_express_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'PaypalExpressGateway' does not match filename 'paypal_express_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/gateway_common\/ReturnUrl.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PayPalAmount.php":{"errors":1,"warnings":0,"messages":[{"message":"Method name \"is_fractional_currency\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":11,"column":19}]},"\/src\/repo\/gateway_common\/RecurringConversion.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/CurrencyCountryRule.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ErrorState.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationLogProcessor.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/UnstagingHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DlocalGateway' does not match filename 'dlocal_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":13,"column":1}]},"\/src\/repo\/modules\/CurrencyRatesModule.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationLoggerFactory.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StagingHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/email_forms\/EmailForm.php":{"errors":0,"warnings":1,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5}]},"\/src\/repo\/gateway_common\/DonorLocale.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ConfigurationReader.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/email_forms\/RequestNewChecksumLinkTrait.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/employerSearch.api.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'EmployerSearchAPI' does not match filename 'employerSearch.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":17,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":32,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":37,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":42,"column":5}]},"\/src\/repo\/gateway_common\/RecurringConversionTrait.php":{"errors":4,"warnings":0,"messages":[{"message":"Method name \"session_getData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":13,"column":21},{"message":"Method name \"session_resetForNewAttempt\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":19,"column":21},{"message":"Method name \"session_setDonorBackupData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":22,"column":21},{"message":"Method name \"session_MoveDonorDataToBackupForRecurringConversion\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":110,"column":12}]},"\/src\/repo\/gateway_common\/DonationApiBase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ValidationHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/AmountInCents.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiDonationClientError.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ContributionTrackingPlusUnique.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":17,"column":75}]},"\/src\/repo\/gateway_common\/GatewayType.php":{"errors":3,"warnings":0,"messages":[{"message":"Method name \"getData_Unstaged_Escaped\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":92,"column":12},{"message":"Method name \"session_ensure\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":198,"column":12},{"message":"Method name \"token_getSaltedSessionToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":240,"column":12}]},"\/src\/repo\/gateway_common\/FiscalNumber.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/extras.body.php":{"errors":4,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras' does not match filename 'extras.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":7,"column":10},{"message":"Class name \"Gateway_Extras\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":7,"column":16},{"message":"Method name \"generate_hash\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":59,"column":15},{"message":"Method name \"compare_hash\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":70,"column":15}]},"\/src\/repo\/gateway_common\/WmfFramework.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":25,"column":30}]},"\/src\/repo\/gateway_common\/SmsOptin.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/FraudFilters\/PreAuthorizeFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/DonationInterface.class.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DonationInterface' does not match filename 'DonationInterface.class.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":7,"column":1}]},"\/src\/repo\/extras\/conversion_log\/conversion_log.body.php":{"errors":3,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras_ConversionLog' does not match filename 'conversion_log.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":5,"column":1},{"message":"Class name \"Gateway_Extras_ConversionLog\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":5,"column":7},{"message":"Method name \"post_process\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":14,"column":15}]},"\/src\/repo\/amazon_gateway\/amazon.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AmazonBillingApi' does not match filename 'amazon.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/includes\/DonorPortal\/ActivityTrackingTrait.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StreetNumberValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestCancelRecurring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/Amount.php":{"errors":2,"warnings":0,"messages":[{"message":"Method name \"is_fractional_currency\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":156,"column":19},{"message":"Method name \"is_exponent3_currency\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":174,"column":19}]},"\/src\/repo\/gateway_common\/ArrayHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/maintenance\/TestCrash.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/amazon_gateway\/amazon_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AmazonGateway' does not match filename 'amazon_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":20,"column":1}]},"\/src\/repo\/amazon_gateway\/amazon_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PaymentResult.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/FraudFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestPauseRecurring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRecurUpgradeClientError.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/paypal_ec_gateway\/paypal_express.adapter.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'PaypalExpressAdapter' does not match filename 'paypal_express.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":24,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":25,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":26,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":27,"column":5}]},"\/src\/repo\/includes\/Api\/ApiRequestLogout.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ResultPages.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":104,"column":18}]},"\/src\/repo\/gravy_gateway\/Gravy3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/gravy_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/FraudFilters\/VelocityFilterRunner.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/Frictionless3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/RecurUpgrade\/Validator.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StreetAddressValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationProfiler.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PostalCodeValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/LocalClusterPsr6Cache.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/DonorPortal\/Hooks.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationInterfaceApiTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseDlocalTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/IngenicoLocale.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree.adapter.php":{"errors":1,"warnings":6,"messages":[{"message":"Class name 'BraintreeAdapter' does not match filename 'braintree.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":14,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":17,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":18,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":19,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":51,"column":78},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":56,"column":55},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":57,"column":74}]},"\/src\/repo\/gateway_common\/Abstract3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/ArrayHelperTest.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":104,"column":36}]},"\/src\/repo\/gateway_common\/EmployerFieldValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/donation.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DonationApi' does not match filename 'donation.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":11,"column":1}]},"\/src\/repo\/includes\/Api\/ApiRequestAnnualConversion.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseAdyenCheckoutTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PaymentTransactionResponse.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/ingenico_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'IngenicoGateway' does not match filename 'ingenico_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":24,"column":1}]},"\/src\/repo\/braintree_gateway\/braintree.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'BraintreeDonationApi' does not match filename 'braintree.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/gateway_common\/RecurringConversion.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'RecurringConversionApi' does not match filename 'RecurringConversion.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":5,"column":1}]},"\/src\/repo\/includes\/FraudFilters\/GenericVelocityFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/CiviproxyConnectTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseGravyTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestNewChecksumLink.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/IngenicoFormVariant.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal.adapter.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'DlocalAdapter' does not match filename 'dlocal.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":17,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":23,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":28,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":33,"column":5}]},"\/src\/repo\/ingenico_gateway\/Ingenico3DSecure.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/MinFraudTestTrait.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/dlocal_gateway\/dlocal.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'DlocalDonationApi' does not match filename 'dlocal.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/tests\/phpunit\/IngenicoLocaleTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/TestingGenericAdapter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRecurringModifyBase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/Api\/ApiRequestUpdateRecurring.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/PaymentSettings.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/TestingGatewayPage.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/braintree_gateway\/braintree_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'BraintreeGateway' does not match filename 'braintree_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":11,"column":1}]},"\/src\/repo\/gravy_gateway\/gravy_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyGatewayResult' does not match filename 'gravy_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/gravy_gateway\/gravy_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyGateway' does not match filename 'gravy_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":10,"column":1}]},"\/src\/repo\/tests\/phpunit\/includes\/test_request\/test.request.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'TestingRequest' does not match filename 'test.request.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":27,"column":1}]},"\/src\/repo\/gravy_gateway\/gravy.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyDonationApi' does not match filename 'gravy.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/tests\/phpunit\/GatewayPageTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/IntegrationTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/RealTimeBankTransferIdealTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationMessageTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/TestingDonationLogger.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DataValidator.php":{"errors":13,"warnings":1,"messages":[{"message":"Method name \"validate_email\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":238,"column":22},{"message":"Method name \"validate_currency_code\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":244,"column":22},{"message":"Method name \"validate_boolean\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":258,"column":22},{"message":"Method name \"validate_numeric\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":278,"column":22},{"message":"Method name \"validate_gateway\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":293,"column":22},{"message":"Method name \"validate_not_empty\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":307,"column":22},{"message":"Method name \"validate_not_just_punctuation\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":319,"column":19},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":320,"column":48},{"message":"Method name \"validate_name\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":335,"column":19},{"message":"Method name \"validate_address\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":345,"column":19},{"message":"Method name \"special_characters_in_wrong_locations\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":363,"column":19},{"message":"Method name \"cc_number_exists_in_str\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":386,"column":19},{"message":"Method name \"luhn_check\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":449,"column":19},{"message":"Method name \"ip_is_listed\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":505,"column":19}]},"\/src\/repo\/ingenico_gateway\/ingenico.adapter.php":{"errors":1,"warnings":3,"messages":[{"message":"Class name 'IngenicoAdapter' does not match filename 'ingenico.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":16,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":19,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":20,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":21,"column":5}]},"\/src\/repo\/includes\/Api\/ApiClientErrorBase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ClientSideValidationHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/custom_filters.body.php":{"errors":2,"warnings":3,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters' does not match filename 'custom_filters.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":9,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":9,"column":7},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":12,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":48,"column":50}]},"\/src\/repo\/gravy_gateway\/gravy_apple.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyAppleApi' does not match filename 'gravy_apple.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":10,"column":1}]},"\/src\/repo\/adyen_gateway\/adyen.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenDonationApi' does not match filename 'adyen.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":2,"column":1}]},"\/src\/repo\/gateway_forms\/MustacheHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/IngenicoReturnUrlHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PaymentMethod.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/RecurUpgrade.php":{"errors":0,"warnings":5,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":16,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":17,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":18,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":20,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":23,"column":5}]},"\/src\/repo\/tests\/phpunit\/DataValidatorTest.php":{"errors":0,"warnings":7,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":102,"column":34},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":103,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":104,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":106,"column":47},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":107,"column":51},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":118,"column":46},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":124,"column":33}]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/TestingPaypalExpressAdapter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/MustacheFormTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/FraudFilters\/GenericPatternFilter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/BlankAddressFields.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/ingenico_gateway\/ingenico_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'IngenicoGatewayResult' does not match filename 'ingenico_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1}]},"\/src\/repo\/ingenico_gateway\/ingenico_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/FundraiserMaintenance.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen_apple.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenAppleApi' does not match filename 'adyen_apple.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":10,"column":1}]},"\/src\/repo\/gateway_common\/EndowmentHooks.php":{"errors":0,"warnings":1,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":11,"column":5}]},"\/src\/repo\/tests\/phpunit\/LoggingTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/RecurringTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/test.adapter.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'TTestingAdapter' does not match filename 'test.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":20,"column":1}]},"\/src\/repo\/tests\/phpunit\/includes\/test_gateway\/TestingDlocalAdapter.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/PaypalTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/includes\/FraudFilters\/PatternFilterRunner.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/source\/source.body.php":{"errors":2,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_Source' does not match filename 'source.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_Source\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":3,"column":7}]},"\/src\/repo\/tests\/phpunit\/GatewayValidationTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/EmailPreferencesTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_forms\/MustacheErrorForm.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen_get_payment_methods.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenGetPaymentMethodsApi' does not match filename 'adyen_get_payment_methods.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":8,"column":1}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Amazon\/AmazonApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen_checkout_resultswitcher.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenCheckoutGatewayResult' does not match filename 'adyen_checkout_resultswitcher.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenFormLoadTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/civiproxy\/CiviproxyConnect.php":{"errors":0,"warnings":2,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":12,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":13,"column":5}]},"\/src\/repo\/extras\/custom_filters\/filters\/minfraud\/minfraud.body.php":{"errors":2,"warnings":3,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_MinFraud' does not match filename 'minfraud.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":44,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_MinFraud\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":44,"column":7},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":272,"column":47},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":280,"column":16},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":288,"column":50}]},"\/src\/repo\/gateway_common\/GatewayPage.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":374,"column":18}]},"\/src\/repo\/gateway_common\/CountryValidation.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/PlaceholderFiscalNumber.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":13,"column":31},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":14,"column":31}]},"\/src\/repo\/gateway_common\/messages\/MessagesEs_419.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseIngenicoTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen_checkout_gateway.body.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenCheckoutGateway' does not match filename 'adyen_checkout_gateway.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":12,"column":1}]},"\/src\/repo\/includes\/Validation\/AmountHelper.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/ResultSwitcher.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/functions\/functions.body.php":{"errors":2,"warnings":1,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_Functions' does not match filename 'functions.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_Functions\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":3,"column":7},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":53,"column":29}]},"\/src\/repo\/amazon_gateway\/amazon.adapter.php":{"errors":1,"warnings":8,"messages":[{"message":"Class name 'AmazonAdapter' does not match filename 'amazon.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":34,"column":1},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":36,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":37,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":38,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":227,"column":73},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":312,"column":36},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":314,"column":41},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":366,"column":36},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":370,"column":41}]},"\/src\/repo\/gateway_forms\/includes\/Subdivisions.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/AmountTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/SecureFieldsCardTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/StreetAddress.php":{"errors":2,"warnings":2,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":6,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":7,"column":5},{"message":"Method name \"stage_street\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":26,"column":15},{"message":"Method name \"stage_postal_code\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":48,"column":15}]},"\/src\/repo\/tests\/phpunit\/unit\/RecurUpgrade\/ValidatorTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/referrer\/referrer.body.php":{"errors":2,"warnings":0,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_Referrer' does not match filename 'referrer.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":3,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_Referrer\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":3,"column":7}]},"\/src\/repo\/special\/GatewayChooser.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":151,"column":41}]},"\/src\/repo\/special\/SystemStatus.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/ApplePayTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/extras\/custom_filters\/filters\/ip_velocity\/ip_velocity.body.php":{"errors":2,"warnings":1,"messages":[{"message":"Class name 'Gateway_Extras_CustomFilters_IP_Velocity' does not match filename 'ip_velocity.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":6,"column":1},{"message":"Class name \"Gateway_Extras_CustomFilters_IP_Velocity\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":6,"column":7},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":110,"column":66}]},"\/src\/repo\/extras\/session_velocity\/session_velocity.body.php":{"errors":2,"warnings":5,"messages":[{"message":"Class name 'Gateway_Extras_SessionVelocityFilter' does not match filename 'session_velocity.body.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":18,"column":1},{"message":"Class name \"Gateway_Extras_SessionVelocityFilter\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":18,"column":7},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":33,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":34,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":35,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":36,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":37,"column":5}]},"\/src\/repo\/gateway_forms\/Mustache.php":{"errors":2,"warnings":1,"messages":[{"message":"Class name 'Gateway_Form_Mustache' does not match filename 'Mustache.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":13,"column":1},{"message":"Class name \"Gateway_Form_Mustache\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":13,"column":7},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Amazon\/AmazonTest.php":{"errors":0,"warnings":5,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":134,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":164,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":191,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":216,"column":63},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":245,"column":63}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Dlocal\/CardPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gravy_gateway\/gravy.adapter.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'GravyAdapter' does not match filename 'gravy.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":22,"column":1}]},"\/src\/repo\/adyen_gateway\/adyen_submit_payment.api.php":{"errors":1,"warnings":0,"messages":[{"message":"Class name 'AdyenSubmitPaymentApi' does not match filename 'adyen_submit_payment.api.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":11,"column":1}]},"\/src\/repo\/adyen_gateway\/adyen_gateway.alias.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/adyen_checkout.adapter.php":{"errors":1,"warnings":1,"messages":[{"message":"Class name 'AdyenCheckoutAdapter' does not match filename 'adyen_checkout.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":13,"column":1},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":276,"column":25}]},"\/src\/repo\/gravy_gateway\/PlaceholderPhoneNumber.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/adyen_gateway\/EncryptedCardParameters.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_forms\/Form.php":{"errors":2,"warnings":0,"messages":[{"message":"Class name 'Gateway_Form' does not match filename 'Form.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":5,"column":10},{"message":"Class name \"Gateway_Form\" is not in PascalCase format","source":"Squiz.Classes.ValidClassName.NotCamelCaps","severity":5,"fixable":false,"type":"ERROR","line":5,"column":16}]},"\/src\/repo\/.phan\/config.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/GatewayAdapterTest.php":{"errors":1,"warnings":5,"messages":[{"message":"Method name \"TestSetValidationAction\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":538,"column":12},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":566,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":600,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":616,"column":61},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":634,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":665,"column":39}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/CheckoutIdealTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/special\/EmailPreferences.php":{"errors":0,"warnings":5,"messages":[{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":13,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":14,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":15,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":18,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":20,"column":5}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenSubmitApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/GravyFormLoadTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Dlocal\/CashPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonationData.php":{"errors":0,"warnings":21,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":60,"column":30},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":69,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":70,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":73,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":74,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":79,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":84,"column":24},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":103,"column":31},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":107,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":122,"column":29},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":125,"column":26},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":126,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":131,"column":26},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":134,"column":29},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":139,"column":22},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":367,"column":41},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":395,"column":72},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":400,"column":50},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":406,"column":34},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":407,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":584,"column":28}]},"\/src\/repo\/gateway_common\/MediaWikiLogHandler.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/BaseBraintreeTestCase.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/DonorEmail.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/EmployerSearchApiTest.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":116,"column":49}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/GooglePayTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/MessageUtils.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Gravy\/RedirectFormTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonorLocaleTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationDataTest.php":{"errors":0,"warnings":11,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":86,"column":91},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":146,"column":59},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":194,"column":91},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":241,"column":102},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":261,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":270,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":280,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":290,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":301,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":329,"column":98},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":342,"column":98}]},"\/src\/repo\/tests\/phpunit\/IPVelocityTest.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":144,"column":64},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":209,"column":64}]},"\/src\/repo\/special\/DonorPortal.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":161,"column":28}]},"\/src\/repo\/tests\/phpunit\/Adapter\/PayPal\/PayPalExpressTest.php":{"errors":0,"warnings":6,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":120,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":210,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":355,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":967,"column":45},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1030,"column":45},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1066,"column":45}]},"\/src\/repo\/tests\/phpunit\/DonationInterfaceTestCase.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":176,"column":23},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":682,"column":51}]},"\/src\/repo\/tests\/phpunit\/GatewayChooserTest.php":{"errors":0,"warnings":5,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":235,"column":131},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":236,"column":131},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":237,"column":127},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":513,"column":76},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":546,"column":67}]},"\/src\/repo\/tests\/phpunit\/Adapter\/PayPal\/PayPalApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/FraudFiltersTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/DonationQueueTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/IngenicoTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/LintYaml.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/TestConfiguration.php":{"errors":0,"warnings":2,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":160,"column":34},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":161,"column":57}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Braintree\/PaypalPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Braintree\/VenmoPaymentTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/IngenicoApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/CheckoutCardTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Ingenico\/ResultSwitcherTest.php":{"errors":0,"warnings":1,"messages":[{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":59,"column":33}]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenRecurringTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/tests\/phpunit\/Adapter\/Adyen\/AdyenGetPaymentMethodsApiTest.php":{"errors":0,"warnings":0,"messages":[]},"\/src\/repo\/gateway_common\/gateway.adapter.php":{"errors":19,"warnings":24,"messages":[{"message":"Class name 'GatewayAdapter' does not match filename 'gateway.adapter.php'","source":"MediaWiki.Files.ClassMatchesFilename.NotMatch","severity":5,"fixable":false,"type":"ERROR","line":40,"column":10},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":44,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":45,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":184,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":185,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":186,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":186,"column":48},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":187,"column":5},{"message":"Visibility must be declared on all constants if your project supports PHP 7.1 or later","source":"PSR12.Properties.ConstantVisibility.NotFound","severity":5,"fixable":false,"type":"WARNING","line":188,"column":5},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":226,"column":41},{"message":"Method name \"getData_Staged\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":488,"column":15},{"message":"Method name \"getData_Unstaged_Escaped\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":581,"column":12},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1099,"column":25},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1482,"column":61},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":1503,"column":59},{"message":"Method name \"session_ensure\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2143,"column":12},{"message":"Method name \"session_getData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2154,"column":12},{"message":"Method name \"session_hasDonorData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2175,"column":12},{"message":"Method name \"session_setDonorBackupData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2184,"column":12},{"message":"Method name \"session_unsetDonorData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2193,"column":12},{"message":"Method name \"session_addDonorData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2203,"column":12},{"message":"Method name \"session_killAllEverything\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2221,"column":12},{"message":"Method name \"session_unsetAllData\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2233,"column":12},{"message":"Method name \"session_resetForNewAttempt\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2249,"column":12},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2267,"column":33},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2272,"column":28},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2280,"column":40},{"message":"Method name \"session_resetOnSwitch\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2315,"column":15},{"message":"Method name \"token_applyMD5AndSalt\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2390,"column":22},{"message":"Method name \"token_generateToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2408,"column":19},{"message":"Method name \"token_getSaltedSessionToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2413,"column":12},{"message":"Method name \"token_refreshAllTokenEverything\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2435,"column":15},{"message":"Method name \"token_matchEditToken\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2455,"column":15},{"message":"Method name \"token_checkTokens\" should use lower camel case.","source":"MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName","severity":5,"fixable":false,"type":"ERROR","line":2480,"column":15},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2481,"column":31},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2520,"column":64},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2618,"column":106},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2676,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2690,"column":59},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2743,"column":45},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2744,"column":39},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2885,"column":27},{"message":"Comments should start on new line.","source":"MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment","severity":5,"fixable":false,"type":"WARNING","line":2898,"column":27}]},"\/src\/repo\/gateway_common\/IsoDate.php":{"errors":0,"warnings":0,"messages":[]}}}

--- end ---
$ git checkout /src/repo/.phpcs.xml
--- stderr ---
Updated 1 path from the index
--- stdout ---

--- end ---
$ /usr/bin/composer install
--- stderr ---
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating optimized autoload files
31 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
--- stdout ---

--- end ---
$ /usr/bin/composer test
--- stderr ---
> parallel-lint . --exclude vendor --exclude node_modules
> phpcs -p -s --cache
> php tests/phpunit/LintYaml.php
> minus-x check .
--- stdout ---
PHP 8.4.18 | 10 parallel jobs
............................................................  60/216 ( 27%)
............................................................ 120/216 ( 55%)
............................................................ 180/216 ( 83%)
....................................                         216/216 (100%)


Checked 216 files in 0.8 seconds
No syntax error found
...................................................... 54 / 54 (100%)


Time: 451ms; Memory: 18MB

MinusX
======
Processing /src/repo...
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.............................................................
.....
All good!

--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "@tootallnate/once": {
      "name": "@tootallnate/once",
      "severity": "low",
      "isDirect": false,
      "via": [
        {
          "source": 1113977,
          "name": "@tootallnate/once",
          "dependency": "@tootallnate/once",
          "title": "@tootallnate/once vulnerable to Incorrect Control Flow Scoping",
          "url": "https://github.com/advisories/GHSA-vpq2-c234-7xj6",
          "severity": "low",
          "cwe": [
            "CWE-705"
          ],
          "cvss": {
            "score": 3.3,
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L"
          },
          "range": "<3.0.1"
        }
      ],
      "effects": [
        "http-proxy-agent"
      ],
      "range": "<3.0.1",
      "nodes": [
        "node_modules/@tootallnate/once"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "babel-core": {
      "name": "babel-core",
      "severity": "critical",
      "isDirect": true,
      "via": [
        "babel-helpers",
        "babel-register",
        "babel-template",
        "babel-traverse",
        "json5"
      ],
      "effects": [
        "babel-register"
      ],
      "range": "5.8.20 - 7.0.0-beta.3",
      "nodes": [
        "node_modules/babel-core"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    },
    "babel-helpers": {
      "name": "babel-helpers",
      "severity": "critical",
      "isDirect": false,
      "via": [
        "babel-template"
      ],
      "effects": [],
      "range": "*",
      "nodes": [
        "node_modules/babel-helpers"
      ],
      "fixAvailable": true
    },
    "babel-register": {
      "name": "babel-register",
      "severity": "high",
      "isDirect": false,
      "via": [
        "babel-core"
      ],
      "effects": [
        "babel-core"
      ],
      "range": "*",
      "nodes": [
        "node_modules/babel-register"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    },
    "babel-template": {
      "name": "babel-template",
      "severity": "critical",
      "isDirect": false,
      "via": [
        "babel-traverse"
      ],
      "effects": [
        "babel-helpers"
      ],
      "range": "*",
      "nodes": [
        "node_modules/babel-template"
      ],
      "fixAvailable": true
    },
    "babel-traverse": {
      "name": "babel-traverse",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1117412,
          "name": "babel-traverse",
          "dependency": "babel-traverse",
          "title": "Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code",
          "url": "https://github.com/advisories/GHSA-67hx-6x53-jw92",
          "severity": "critical",
          "cwe": [
            "CWE-184",
            "CWE-697"
          ],
          "cvss": {
            "score": 9.3,
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
          },
          "range": "<7.23.2"
        }
      ],
      "effects": [
        "babel-core",
        "babel-template"
      ],
      "range": "*",
      "nodes": [
        "node_modules/babel-traverse"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    },
    "http-proxy-agent": {
      "name": "http-proxy-agent",
      "severity": "low",
      "isDirect": false,
      "via": [
        "@tootallnate/once"
      ],
      "effects": [
        "jsdom"
      ],
      "range": "4.0.1 - 5.0.0",
      "nodes": [
        "node_modules/http-proxy-agent"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "jest-environment-jsdom": {
      "name": "jest-environment-jsdom",
      "severity": "low",
      "isDirect": true,
      "via": [
        "jsdom"
      ],
      "effects": [],
      "range": "27.0.1 - 30.0.0-rc.1",
      "nodes": [
        "node_modules/jest-environment-jsdom"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "jsdom": {
      "name": "jsdom",
      "severity": "low",
      "isDirect": false,
      "via": [
        "http-proxy-agent"
      ],
      "effects": [
        "jest-environment-jsdom"
      ],
      "range": "16.6.0 - 22.1.0",
      "nodes": [
        "node_modules/jsdom"
      ],
      "fixAvailable": {
        "name": "jest-environment-jsdom",
        "version": "30.3.0",
        "isSemVerMajor": true
      }
    },
    "json5": {
      "name": "json5",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1096543,
          "name": "json5",
          "dependency": "json5",
          "title": "Prototype Pollution in JSON5 via Parse Method",
          "url": "https://github.com/advisories/GHSA-9c47-m6qq-7p4h",
          "severity": "high",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 7.1,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:H"
          },
          "range": "<1.0.2"
        }
      ],
      "effects": [
        "babel-core"
      ],
      "range": "<1.0.2",
      "nodes": [
        "node_modules/babel-core/node_modules/json5"
      ],
      "fixAvailable": {
        "name": "babel-core",
        "version": "4.7.16",
        "isSemVerMajor": true
      }
    }
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 4,
      "moderate": 0,
      "high": 2,
      "critical": 4,
      "total": 10
    },
    "dependencies": {
      "prod": 1,
      "dev": 1116,
      "optional": 3,
      "peer": 2,
      "peerOptional": 0,
      "total": 1116
    }
  }
}

--- end ---
Attempting to npm audit fix
$ /usr/bin/npm audit fix --dry-run --only=dev --json
--- stderr ---
npm WARN invalid config only="dev" set in command line options
npm WARN invalid config Must be one of: null, prod, production
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex-icons@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
--- stdout ---
{
  "added": 1,
  "removed": 0,
  "changed": 1,
  "audited": 1117,
  "funding": 160,
  "audit": {
    "auditReportVersion": 2,
    "vulnerabilities": {
      "@tootallnate/once": {
        "name": "@tootallnate/once",
        "severity": "low",
        "isDirect": false,
        "via": [
          {
            "source": 1113977,
            "name": "@tootallnate/once",
            "dependency": "@tootallnate/once",
            "title": "@tootallnate/once vulnerable to Incorrect Control Flow Scoping",
            "url": "https://github.com/advisories/GHSA-vpq2-c234-7xj6",
            "severity": "low",
            "cwe": [
              "CWE-705"
            ],
            "cvss": {
              "score": 3.3,
              "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L"
            },
            "range": "<3.0.1"
          }
        ],
        "effects": [
          "http-proxy-agent"
        ],
        "range": "<3.0.1",
        "nodes": [
          ""
        ],
        "fixAvailable": {
          "name": "jest-environment-jsdom",
          "version": "30.3.0",
          "isSemVerMajor": true
        }
      },
      "babel-core": {
        "name": "babel-core",
        "severity": "critical",
        "isDirect": true,
        "via": [
          "babel-helpers",
          "babel-register",
          "babel-template",
          "babel-traverse",
          "json5"
        ],
        "effects": [
          "babel-register"
        ],
        "range": "5.8.20 - 7.0.0-beta.3",
        "nodes": [
          "node_modules/babel-core"
        ],
        "fixAvailable": {
          "name": "babel-core",
          "version": "4.7.16",
          "isSemVerMajor": true
        }
      },
      "babel-helpers": {
        "name": "babel-helpers",
        "severity": "critical",
        "isDirect": false,
        "via": [
          "babel-template"
        ],
        "effects": [],
        "range": "*",
        "nodes": [
          "node_modules/babel-helpers"
        ],
        "fixAvailable": true
      },
      "babel-register": {
        "name": "babel-register",
        "severity": "high",
        "isDirect": false,
        "via": [
          "babel-core"
        ],
        "effects": [
          "babel-core"
        ],
        "range": "*",
        "nodes": [
          "node_modules/babel-register"
        ],
        "fixAvailable": {
          "name": "babel-core",
          "version": "4.7.16",
          "isSemVerMajor": true
        }
      },
      "babel-template": {
        "name": "babel-template",
        "severity": "critical",
        "isDirect": false,
        "via": [
          "babel-traverse"
        ],
        "effects": [
          "babel-helpers"
        ],
        "range": "*",
        "nodes": [
          "node_modules/babel-template"
        ],
        "fixAvailable": true
      },
      "babel-traverse": {
        "name": "babel-traverse",
        "severity": "critical",
        "isDirect": false,
        "via": [
          {
            "source": 1117412,
            "name": "babel-traverse",
            "dependency": "babel-traverse",
            "title": "Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code",
            "url": "https://github.com/advisories/GHSA-67hx-6x53-jw92",
            "severity": "critical",
            "cwe": [
              "CWE-184",
              "CWE-697"
            ],
            "cvss": {
              "score": 9.3,
              "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
            },
            "range": "<7.23.2"
          }
        ],
        "effects": [
          "babel-core",
          "babel-template"
        ],
        "range": "*",
        "nodes": [
          "node_modules/babel-traverse"
        ],
        "fixAvailable": {
          "name": "babel-core",
          "version": "4.7.16",
          "isSemVerMajor": true
        }
      },
      "http-proxy-agent": {
        "name": "http-proxy-agent",
        "severity": "low",
        "isDirect": false,
        "via": [
          "@tootallnate/once"
        ],
        "effects": [
          "jsdom"
        ],
        "range": "4.0.1 - 5.0.0",
        "nodes": [
          "node_modules/http-proxy-agent"
        ],
        "fixAvailable": {
          "name": "jest-environment-jsdom",
          "version": "30.3.0",
          "isSemVerMajor": true
        }
      },
      "jest-environment-jsdom": {
        "name": "jest-environment-jsdom",
        "severity": "low",
        "isDirect": true,
        "via": [
          "jsdom"
        ],
        "effects": [],
        "range": "27.0.1 - 30.0.0-rc.1",
        "nodes": [
          "node_modules/jest-environment-jsdom"
        ],
        "fixAvailable": {
          "name": "jest-environment-jsdom",
          "version": "30.3.0",
          "isSemVerMajor": true
        }
      },
      "jsdom": {
        "name": "jsdom",
        "severity": "low",
        "isDirect": false,
        "via": [
          "http-proxy-agent"
        ],
        "effects": [
          "jest-environment-jsdom"
        ],
        "range": "16.6.0 - 22.1.0",
        "nodes": [
          "node_modules/jsdom"
        ],
        "fixAvailable": {
          "name": "jest-environment-jsdom",
          "version": "30.3.0",
          "isSemVerMajor": true
        }
      },
      "json5": {
        "name": "json5",
        "severity": "high",
        "isDirect": false,
        "via": [
          {
            "source": 1096543,
            "name": "json5",
            "dependency": "json5",
            "title": "Prototype Pollution in JSON5 via Parse Method",
            "url": "https://github.com/advisories/GHSA-9c47-m6qq-7p4h",
            "severity": "high",
            "cwe": [
              "CWE-1321"
            ],
            "cvss": {
              "score": 7.1,
              "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:H"
            },
            "range": "<1.0.2"
          }
        ],
        "effects": [
          "babel-core"
        ],
        "range": "<1.0.2",
        "nodes": [
          "node_modules/babel-core/node_modules/json5"
        ],
        "fixAvailable": {
          "name": "babel-core",
          "version": "4.7.16",
          "isSemVerMajor": true
        }
      }
    },
    "metadata": {
      "vulnerabilities": {
        "info": 0,
        "low": 4,
        "moderate": 0,
        "high": 2,
        "critical": 4,
        "total": 10
      },
      "dependencies": {
        "prod": 1,
        "dev": 1116,
        "optional": 3,
        "peer": 2,
        "peerOptional": 0,
        "total": 1116
      }
    }
  }
}

--- end ---
{"added": 1, "removed": 0, "changed": 1, "audited": 1117, "funding": 160, "audit": {"auditReportVersion": 2, "vulnerabilities": {"@tootallnate/once": {"name": "@tootallnate/once", "severity": "low", "isDirect": false, "via": [{"source": 1113977, "name": "@tootallnate/once", "dependency": "@tootallnate/once", "title": "@tootallnate/once vulnerable to Incorrect Control Flow Scoping", "url": "https://github.com/advisories/GHSA-vpq2-c234-7xj6", "severity": "low", "cwe": ["CWE-705"], "cvss": {"score": 3.3, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L"}, "range": "<3.0.1"}], "effects": ["http-proxy-agent"], "range": "<3.0.1", "nodes": [""], "fixAvailable": {"name": "jest-environment-jsdom", "version": "30.3.0", "isSemVerMajor": true}}, "babel-core": {"name": "babel-core", "severity": "critical", "isDirect": true, "via": ["babel-helpers", "babel-register", "babel-template", "babel-traverse", "json5"], "effects": ["babel-register"], "range": "5.8.20 - 7.0.0-beta.3", "nodes": ["node_modules/babel-core"], "fixAvailable": {"name": "babel-core", "version": "4.7.16", "isSemVerMajor": true}}, "babel-helpers": {"name": "babel-helpers", "severity": "critical", "isDirect": false, "via": ["babel-template"], "effects": [], "range": "*", "nodes": ["node_modules/babel-helpers"], "fixAvailable": true}, "babel-register": {"name": "babel-register", "severity": "high", "isDirect": false, "via": ["babel-core"], "effects": ["babel-core"], "range": "*", "nodes": ["node_modules/babel-register"], "fixAvailable": {"name": "babel-core", "version": "4.7.16", "isSemVerMajor": true}}, "babel-template": {"name": "babel-template", "severity": "critical", "isDirect": false, "via": ["babel-traverse"], "effects": ["babel-helpers"], "range": "*", "nodes": ["node_modules/babel-template"], "fixAvailable": true}, "babel-traverse": {"name": "babel-traverse", "severity": "critical", "isDirect": false, "via": [{"source": 1117412, "name": "babel-traverse", "dependency": "babel-traverse", "title": "Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code", "url": "https://github.com/advisories/GHSA-67hx-6x53-jw92", "severity": "critical", "cwe": ["CWE-184", "CWE-697"], "cvss": {"score": 9.3, "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"}, "range": "<7.23.2"}], "effects": ["babel-core", "babel-template"], "range": "*", "nodes": ["node_modules/babel-traverse"], "fixAvailable": {"name": "babel-core", "version": "4.7.16", "isSemVerMajor": true}}, "http-proxy-agent": {"name": "http-proxy-agent", "severity": "low", "isDirect": false, "via": ["@tootallnate/once"], "effects": ["jsdom"], "range": "4.0.1 - 5.0.0", "nodes": ["node_modules/http-proxy-agent"], "fixAvailable": {"name": "jest-environment-jsdom", "version": "30.3.0", "isSemVerMajor": true}}, "jest-environment-jsdom": {"name": "jest-environment-jsdom", "severity": "low", "isDirect": true, "via": ["jsdom"], "effects": [], "range": "27.0.1 - 30.0.0-rc.1", "nodes": ["node_modules/jest-environment-jsdom"], "fixAvailable": {"name": "jest-environment-jsdom", "version": "30.3.0", "isSemVerMajor": true}}, "jsdom": {"name": "jsdom", "severity": "low", "isDirect": false, "via": ["http-proxy-agent"], "effects": ["jest-environment-jsdom"], "range": "16.6.0 - 22.1.0", "nodes": ["node_modules/jsdom"], "fixAvailable": {"name": "jest-environment-jsdom", "version": "30.3.0", "isSemVerMajor": true}}, "json5": {"name": "json5", "severity": "high", "isDirect": false, "via": [{"source": 1096543, "name": "json5", "dependency": "json5", "title": "Prototype Pollution in JSON5 via Parse Method", "url": "https://github.com/advisories/GHSA-9c47-m6qq-7p4h", "severity": "high", "cwe": ["CWE-1321"], "cvss": {"score": 7.1, "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:H"}, "range": "<1.0.2"}], "effects": ["babel-core"], "range": "<1.0.2", "nodes": ["node_modules/babel-core/node_modules/json5"], "fixAvailable": {"name": "babel-core", "version": "4.7.16", "isSemVerMajor": true}}}, "metadata": {"vulnerabilities": {"info": 0, "low": 4, "moderate": 0, "high": 2, "critical": 4, "total": 10}, "dependencies": {"prod": 1, "dev": 1116, "optional": 3, "peer": 2, "peerOptional": 0, "total": 1116}}}}
$ /usr/bin/npm audit fix --only=dev
--- stderr ---
npm WARN invalid config only="dev" set in command line options
npm WARN invalid config Must be one of: null, prod, production
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex-icons@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
--- stdout ---

changed 1 package, and audited 1116 packages in 4s

160 packages are looking for funding
  run `npm fund` for details

# npm audit report

@tootallnate/once  <3.0.1
@tootallnate/once vulnerable to Incorrect Control Flow Scoping - https://github.com/advisories/GHSA-vpq2-c234-7xj6
fix available via `npm audit fix --force`
Will install jest-environment-jsdom@30.3.0, which is a breaking change
node_modules/@tootallnate/once
  http-proxy-agent  4.0.1 - 5.0.0
  Depends on vulnerable versions of @tootallnate/once
  node_modules/http-proxy-agent
    jsdom  16.6.0 - 22.1.0
    Depends on vulnerable versions of http-proxy-agent
    node_modules/jsdom
      jest-environment-jsdom  27.0.1 - 30.0.0-rc.1
      Depends on vulnerable versions of jsdom
      node_modules/jest-environment-jsdom

babel-traverse  *
Severity: critical
Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code - https://github.com/advisories/GHSA-67hx-6x53-jw92
fix available via `npm audit fix --force`
Will install babel-core@4.7.16, which is a breaking change
node_modules/babel-traverse
  babel-core  5.8.20 - 7.0.0-beta.3
  Depends on vulnerable versions of babel-helpers
  Depends on vulnerable versions of babel-register
  Depends on vulnerable versions of babel-template
  Depends on vulnerable versions of babel-traverse
  Depends on vulnerable versions of json5
  node_modules/babel-core
    babel-register  *
    Depends on vulnerable versions of babel-core
    node_modules/babel-register
  babel-template  *
  Depends on vulnerable versions of babel-traverse
  node_modules/babel-template
    babel-helpers  *
    Depends on vulnerable versions of babel-template
    node_modules/babel-helpers

json5  <1.0.2
Severity: high
Prototype Pollution in JSON5 via Parse Method - https://github.com/advisories/GHSA-9c47-m6qq-7p4h
fix available via `npm audit fix --force`
Will install babel-core@4.7.16, which is a breaking change
node_modules/babel-core/node_modules/json5

10 vulnerabilities (4 low, 2 high, 4 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

--- end ---
Verifying that tests still pass
$ /usr/bin/npm ci
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex-icons@2.4.0',
npm WARN EBADENGINE   required: { node: '>=20.19.1', npm: '>=10.8.2' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
npm WARN deprecated osenv@0.1.5: This package is no longer supported.
npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated abab@2.0.6: Use your platform's native atob() and btoa() methods instead
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported
npm WARN deprecated domexception@4.0.0: Use your platform's native DOMException instead
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
npm WARN deprecated core-js@2.6.12: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
--- stdout ---

added 1115 packages, and audited 1116 packages in 14s

160 packages are looking for funding
  run `npm fund` for details

10 vulnerabilities (4 low, 2 high, 4 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

--- end ---
$ /usr/bin/npm test
--- stderr ---
PASS tests/jest/views/update-donations.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/annual-conversion.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <AnnualConversionView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <AnnualConversionView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/cancel-donations.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "TypeError: Cannot read properties of undefined (reading 'next_sched_contribution_date')", got Error  
        at <ErrorComponent key=5 error-code= TypeError: Cannot read properties of undefined (reading 'next_sched_contribution_date')
          at next_sched_contribution_date (/src/repo/modules/ext.donationInterface.donorPortal/views/CancelDonations.vue:59:55) fallback-message-key="donorportal-pause-failure" > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=3 error-code= { result: { message: 'API error' } } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=5 error-code= { result: { message: 'API error' } } fallback-message-key="donorportal-pause-failure" > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=3 error-code= { result: { message: 'API error' } } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=3 error-code= { result: { message: 'API error' } } > 
        at <CancelDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/routes/router.test.js
PASS tests/jest/views/pause-donations.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } fallback-message-key="donorportal-pause-failure" > 
        at <PauseDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } fallback-message-key="donorportal-pause-failure" > 
        at <PauseDonationsView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/home.test.js
PASS tests/jest/views/amount-downgrade.test.js
  ● Console

    console.warn
      [Vue warn]: Invalid prop: type check failed for prop "errorCode". Expected String with value "[object Object]", got Object  
        at <ErrorComponent key=2 error-code= { message: 'API error' } > 
        at <AmountDowngradeView ref="VTU_COMPONENT" > 
        at <VTUROOT>

      at warn$1 (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:53:13)
      at validateProp (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4363:7)
      at validateProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4335:5)
      at initProps (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4036:5)
      at setupComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7807:3)
      at mountComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7)
      at processComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11)
      at patchBlockChildren (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5008:7)
      at patchElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4926:7)
      at processElement (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4785:7)
      at patch (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4642:11)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5349:9)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19)
      at ReactiveEffect.runIfDirty (node_modules/@vue/reactivity/dist/reactivity.cjs.js:267:12)
      at callWithErrorHandling (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:33)
      at flushJobs (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:405:9)

PASS tests/jest/views/login.test.js
PASS tests/jest/components/recurring-cancel-confirmation.test.js
PASS tests/jest/components/donations_history.test.js
PASS tests/jest/components/header.test.js
PASS tests/jest/views/manage-donations.test.js
PASS tests/jest/components/recurring-cancel-form.test.js
PASS tests/jest/components/error-component.test.js
PASS tests/jest/components/recurring-update-form.test.js
PASS tests/jest/components/recurring_contribution.test.js
PASS tests/jest/components/donations_list_table.test.js
PASS tests/jest/components/recurring-update-success.test.js
PASS tests/jest/components/recurring-cancel-success.test.js
PASS tests/jest/components/recurring-pause-form.test.js
PASS tests/jest/components/recurring_contribution_summary.test.js
PASS tests/jest/components/greeting_component.test.js
PASS tests/jest/components/app.test.js
PASS tests/jest/components/onetime_contribution.test.js
PASS tests/jest/components/recurring-cancel-option-container.test.js
PASS tests/jest/components/contact_details.test.js
PASS tests/jest/components/feedback-survey_component.test.js
PASS tests/jest/components/popup_link.test.js
PASS tests/jest/components/recurring-pause-success.test.js

Test Suites: 29 passed, 29 total
Tests:       102 passed, 102 total
Snapshots:   0 total
Time:        7.306 s, estimated 8 s
Ran all test suites.
--- stdout ---

> test
> grunt test && npm run test:unit

Running "eslint:all" (eslint) task

/src/repo/Gruntfile.js
  37:11  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/adyen_gateway/forms/adyen.js
    1:26  warning  'Promise' is already defined as a built-in global variable           no-redeclare
    5:3   warning  'configFromServer' is never reassigned. Use 'const' instead          prefer-const
    6:3   warning  'payment_method' is never reassigned. Use 'const' instead            prefer-const
    8:3   warning  'country' is never reassigned. Use 'const' instead                   prefer-const
    9:3   warning  'language' is never reassigned. Use 'const' instead                  prefer-const
   17:3   warning  'GOOGLEPAY_COMPONENT_TYPE' is never reassigned. Use 'const' instead  prefer-const
   18:3   warning  'ACH_GET_DONOR_ADDRESS' is never reassigned. Use 'const' instead     prefer-const
   25:1   warning  Missing JSDoc @return type                                           jsdoc/require-returns-type
   66:5   warning  Unexpected var, use let or const instead                             no-var
   82:23  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
   84:11  warning  'bContact' is never reassigned. Use 'const' instead                  prefer-const
   85:8   warning  'sContact' is never reassigned. Use 'const' instead                  prefer-const
  133:5   warning  Unexpected var, use let or const instead                             no-var
  164:23  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  223:34  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  227:14  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  313:2   warning  'submitPromise' is never reassigned. Use 'const' instead             prefer-const
  313:22  warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  401:6   warning  ES2015 'Object.assign' method is forbidden                           es-x/no-object-assign
  540:4   warning  ES2015 'Object.assign' method is forbidden                           es-x/no-object-assign
  550:4   warning  'containerName' is never reassigned. Use 'const' instead             prefer-const
  554:3   warning  'component_type' is never reassigned. Use 'const' instead            prefer-const
  573:3   warning  'oldShowErrors' is never reassigned. Use 'const' instead             prefer-const
  595:3   warning  'config' is never reassigned. Use 'const' instead                    prefer-const
  603:3   warning  'checkoutPromise' is never reassigned. Use 'const' instead           prefer-const
  627:4   warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise
  654:4   warning  ES2015 'Promise' class is forbidden                                  es-x/no-promise

/src/repo/amazon_gateway/amazon.js
    3:6   warning  'clientId' is never reassigned. Use 'const' instead                   prefer-const
    4:3   warning  'sellerId' is never reassigned. Use 'const' instead                   prefer-const
    5:3   warning  'sandbox' is never reassigned. Use 'const' instead                    prefer-const
    6:3   warning  'returnUrl' is never reassigned. Use 'const' instead                  prefer-const
    7:3   warning  'widgetScript' is never reassigned. Use 'const' instead               prefer-const
    8:3   warning  'loginScript' is never reassigned. Use 'const' instead                prefer-const
    9:3   warning  'failPage' is never reassigned. Use 'const' instead                   prefer-const
   10:3   warning  'isRecurring' is never reassigned. Use 'const' instead                prefer-const
   14:3   warning  'validTokenPattern' is never reassigned. Use 'const' instead          prefer-const
   14:23  warning  Use a regular expression literal instead of the 'RegExp' constructor  prefer-regex-literals
   22:3   warning  'CARD_SELECT_DELAY' is never reassigned. Use 'const' instead          prefer-const
   98:2   warning  'accessToken' is never reassigned. Use 'const' instead                prefer-const
   99:2   warning  'loginError' is never reassigned. Use 'const' instead                 prefer-const
  129:12  warning  Avoid direct access to document.cookie. Use mw.cookie instead         mediawiki/no-cookie
  268:8   warning  Selector extensions are not allowed                                   no-jquery/no-sizzle

/src/repo/braintree_gateway/forms/braintree.js
  10:6  warning  'di' is never reassigned. Use 'const' instead              prefer-const
  12:3  warning  'payment_method' is never reassigned. Use 'const' instead  prefer-const
  13:3  warning  'scripts' is never reassigned. Use 'const' instead         prefer-const

/src/repo/dlocal_gateway/forms/dlocal.js
  27:7  warning  'dlocalInstance' is never reassigned. Use 'const' instead   prefer-const
  28:4  warning  'fields' is never reassigned. Use 'const' instead           prefer-const
  33:4  warning  'commonStyle' is never reassigned. Use 'const' instead      prefer-const
  49:3  warning  'cardField' is never reassigned. Use 'const' instead        prefer-const
  55:3  warning  'expirationField' is never reassigned. Use 'const' instead  prefer-const
  61:3  warning  'cvvField' is never reassigned. Use 'const' instead         prefer-const

/src/repo/gravy_gateway/forms/gravy.js
  454:43  warning  'appleSession' is already declared in the upper scope on line 14 column 3  no-shadow

/src/repo/modules/ext.donationInterface.donorPortal/ApiUtils.js
  13:16  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsDisclaimerComponent.vue
  4:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  6:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsHistory.vue
  128:25  warning  'panel' is already declared in the upper scope on line 138 column 10  no-shadow

/src/repo/modules/ext.donationInterface.donorPortal/components/DonationsListTable.vue
  21:22  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  41:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionForm.vue
   35:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
   55:37  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  100:34  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionAnnualConversionSuccess.vue
  13:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  15:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionCancelSuccess.vue
  13:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionComponent.vue
  33:29  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionPauseSuccess.vue
  13:31  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/components/RecurringContributionUpdateSuccess.vue
  15:33  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/ext.donationInterface.donorPortal/views/LoginView.vue
   8:6   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  37:7   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  66:8   warning  'v-html' directive can lead to XSS attack  vue/no-v-html
  76:17  warning  'v-html' directive can lead to XSS attack  vue/no-v-html

/src/repo/modules/iframe.liberator.js
  1:10  warning  'self' is already defined as a built-in global variable  no-redeclare

/src/repo/modules/js/ext.donationInterface.applePayHelper.js
  4:1  warning  Missing JSDoc @param "$" type   jsdoc/require-param-type
  5:1  warning  Missing JSDoc @param "mw" type  jsdoc/require-param-type

/src/repo/modules/js/ext.donationInterface.employerAutoComplete.js
  28:21  warning  Prefer .then to .done  no-jquery/no-done-fail

/src/repo/modules/js/ext.donationInterface.errorLog.js
  16:3  warning  'postdata' is never reassigned. Use 'const' instead  prefer-const

/src/repo/modules/js/ext.donationInterface.forms.js
    4:1   warning  Missing JSDoc @param "$" type                        jsdoc/require-param-type
    5:1   warning  Missing JSDoc @param "mw" type                       jsdoc/require-param-type
   74:27  warning  Selector extensions are not allowed                  no-jquery/no-sizzle
   90:12  warning  '$element' is never reassigned. Use 'const' instead  prefer-const
  107:1   warning  Missing JSDoc @param "checkboxName" type             jsdoc/require-param-type
  111:12  warning  '$element' is never reassigned. Use 'const' instead  prefer-const
  126:1   warning  The type 'result' is undefined                       jsdoc/no-undefined-types
  148:3   warning  'sendData' is never reassigned. Use 'const' instead  prefer-const
  187:4   warning  ES2015 'Object.assign' method is forbidden           es-x/no-object-assign
  239:14  warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  269:10  warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  283:4   warning  ES2015 'Promise' class is forbidden                  es-x/no-promise
  321:10  warning  Selector extensions are not allowed                  no-jquery/no-sizzle
  325:30  warning  Selector extensions are not allowed                  no-jquery/no-sizzle

/src/repo/modules/js/ext.donationInterface.jaVariant02.js
  8:1  warning  Missing JSDoc @param "mw" type  jsdoc/require-param-type
  9:1  warning  Missing JSDoc @param "$" type   jsdoc/require-param-type

/src/repo/modules/js/ext.donationInterface.monthlyConvert.js
    2:6   warning  'mc' is never reassigned. Use 'const' instead                         prefer-const
    6:3   warning  'tyUrl' is never reassigned. Use 'const' instead                      prefer-const
    9:3   warning  'convertAmounts' is never reassigned. Use 'const' instead             prefer-const
   17:3   warning  'numAmounts' is never reassigned. Use 'const' instead                 prefer-const
   37:49  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
   78:39  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
  147:51  warning  'currency' is already declared in the upper scope on line 3 column 3  no-shadow
  148:7   warning  'rates' is never reassigned. Use 'const' instead                      prefer-const
  149:4   warning  'amountRules' is never reassigned. Use 'const' instead                prefer-const
  151:4   warning  '$smallAmountMessage' is never reassigned. Use 'const' instead        prefer-const
  161:3   warning  'formattedMin' is never reassigned. Use 'const' instead               prefer-const
  177:4   warning  'locale' is never reassigned. Use 'const' instead                     prefer-const
  180:3   warning  'presetAmount' is never reassigned. Use 'const' instead               prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvertAnnual.js
   3:7   warning  'mc' is never reassigned. Use 'const' instead                        prefer-const
   3:31  warning  'originalGetSendData' is never reassigned. Use 'const' instead       prefer-const
   4:4   warning  'originalAmount' is never reassigned. Use 'const' instead            prefer-const
   5:4   warning  '$otherAmountMonthlyInput' is never reassigned. Use 'const' instead  prefer-const
   5:62  warning  '$otherAmountAnnualInput' is never reassigned. Use 'const' instead   prefer-const
   6:4   warning  '$otherMonthlySubmit' is never reassigned. Use 'const' instead       prefer-const
   6:60  warning  '$otherAnnualSubmit' is never reassigned. Use 'const' instead        prefer-const
   7:4   warning  '$smallAmountMessage' is never reassigned. Use 'const' instead       prefer-const
  15:3   warning  'originalAmountFormatted' is never reassigned. Use 'const' instead   prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvertMultiplier.js
  3:7  warning  'mc' is never reassigned. Use 'const' instead              prefer-const
  4:3  warning  'originalAmount' is never reassigned. Use 'const' instead  prefer-const

/src/repo/modules/js/ext.donationInterface.monthlyConvert_011.js
  3:7  warning  'mc' is never reassigned. Use 'const' instead              prefer-const
  4:4  warning  'locale' is never reassigned. Use 'const' instead          prefer-const
  5:3  warning  'originalAmount' is never reassigned. Use 'const' instead  prefer-const
  6:3  warning  'currency' is never reassigned. Use 'const' instead        prefer-const
  7:3  warning  'presetAmount' is never reassigned. Use 'const' instead    prefer-const
  8:3  warning  'formattedAsk' is never reassigned. Use 'const' instead    prefer-const

/src/repo/modules/js/ext.donationInterface.recurUpgrade.js
   3:7  warning  '$submitButton' is never reassigned. Use 'const' instead      prefer-const
   4:4  warning  '$amountField' is never reassigned. Use 'const' instead       prefer-const
   5:4  warning  '$otherAmountField' is never reassigned. Use 'const' instead  prefer-const
   6:4  warning  '$totalMessage' is never reassigned. Use 'const' instead      prefer-const
   7:4  warning  '$newTotalAmount' is never reassigned. Use 'const' instead    prefer-const
   8:4  warning  '$form' is never reassigned. Use 'const' instead              prefer-const
   9:4  warning  'originalAmount' is never reassigned. Use 'const' instead     prefer-const
  10:4  warning  'currency' is never reassigned. Use 'const' instead           prefer-const
  11:4  warning  'maximum' is never reassigned. Use 'const' instead            prefer-const
  12:4  warning  'nextDateFormatted' is never reassigned. Use 'const' instead  prefer-const
  14:4  warning  'preSelectAmount' is never reassigned. Use 'const' instead    prefer-const
  38:4  warning  'valueIsValid' is never reassigned. Use 'const' instead       prefer-const

/src/repo/modules/js/ext.donationInterface.validation.js
   7:1   warning  Missing JSDoc @param "$" type                                      jsdoc/require-param-type
   8:1   warning  Missing JSDoc @param "mw" type                                     jsdoc/require-param-type
  11:6   warning  'di' is never reassigned. Use 'const' instead                      prefer-const
  13:3   warning  'mcDomains' is never reassigned. Use 'const' instead               prefer-const
  33:3   warning  'multiCountrySubdomains' is never reassigned. Use 'const' instead  prefer-const
  34:3   warning  'countryTlds' is never reassigned. Use 'const' instead             prefer-const
  40:26  warning  'i' is already declared in the upper scope on line 39 column 36    no-shadow

/src/repo/modules/validate_input.js
    1:1   warning  Missing JSDoc @return declaration                                                    jsdoc/require-returns
    9:3   warning  'rates' is never reassigned. Use 'const' instead                                     prefer-const
   10:3   warning  'amountRules' is never reassigned. Use 'const' instead                               prefer-const
   14:3   warning  '$amountMsg' is never reassigned. Use 'const' instead                                prefer-const
   15:3   warning  'threeDecimalCurrencies' is never reassigned. Use 'const' instead                    prefer-const
   86:3   warning  'invalids' is never reassigned. Use 'const' instead                                  prefer-const
   87:3   warning  'rules' is never reassigned. Use 'const' instead                                     prefer-const
  105:27  warning  'value' is already declared in the upper scope on line 82 column 6                   no-shadow
  107:14  warning  All possible message keys should be documented. See https://w.wiki/4r9a for details  mediawiki/msg-doc
  113:23  warning  'i' is already declared in the upper scope on line 85 column 3                       no-shadow
  145:2   warning  'countryField' is never reassigned. Use 'const' instead                              prefer-const
  168:2   warning  'emailAdd' is never reassigned. Use 'const' instead                                  prefer-const
  220:2   warning  'phoneAdd' is never reassigned. Use 'const' instead                                  prefer-const
  241:11  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie
  242:16  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie
  243:12  warning  Avoid direct access to document.cookie. Use mw.cookie instead                        mediawiki/no-cookie

/src/repo/paypal_ec_gateway/forms/js/paypal.js
  2:6  warning  'di' is never reassigned. Use 'const' instead     prefer-const
  3:3  warning  'rules' is never reassigned. Use 'const' instead  prefer-const

/src/repo/tests/jest/components/recurring_contribution.test.js
  57:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign
  71:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign
  88:19  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/amount-downgrade.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/annual-conversion.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/cancel-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/home.test.js
  2:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/manage-donations.test.js
  4:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/pause-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

/src/repo/tests/jest/views/update-donations.test.js
  5:34  warning  ES2015 'Object.assign' method is forbidden  es-x/no-object-assign

✖ 170 problems (0 errors, 170 warnings)


Running "stylelint:all" (stylelint) task
>> Linted 17 files without errors

Running "banana:DonationInterface" (banana) task
>> The "fr" translation has 1 translation with trailing whitespace:
>> * donorportal-coming-soon
>> 10 message directories checked.

Done.

> test:unit
> jest

----------------------------------------------------|---------|----------|---------|---------|-----------------------
File                                                | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s     
----------------------------------------------------|---------|----------|---------|---------|-----------------------
All files                                           |   94.33 |    85.48 |   88.02 |    94.3 |                       
 ext.donationInterface.donorPortal                  |   77.38 |    63.63 |   86.66 |   77.38 |                       
  ApiUtils.js                                       |   93.75 |       50 |     100 |   93.75 | 41                    
  normalizeInput.js                                 |   63.88 |    59.45 |      75 |   63.88 | 4,21,32-35,54-66      
  router.js                                         |   80.76 |    71.42 |      50 |   80.76 | 13-14,20-21,54        
  trackingParams.js                                 |     100 |      100 |     100 |     100 |                       
 ext.donationInterface.donorPortal/components       |   95.13 |    90.65 |   84.77 |   95.13 |                       
  App.vue                                           |     100 |      100 |     100 |     100 |                       
  DonationsDisclaimerComponent.vue                  |     100 |      100 |     100 |     100 |                       
  DonationsHistory.vue                              |   94.44 |      100 |      75 |   94.44 | 16-23                 
  DonationsListTable.vue                            |   89.28 |    94.44 |   73.33 |   89.28 | 23,40,137-153,183-199 
  DonorCardComponent.vue                            |     100 |       90 |     100 |     100 | 78                    
  DonorContactDetails.vue                           |   93.93 |    86.36 |     100 |   93.93 | 46,48                 
  EndowmentInformationComponent.vue                 |     100 |      100 |     100 |     100 |                       
  ErrorComponent.vue                                |     100 |      100 |     100 |     100 |                       
  FeedbackSurveyComponent.vue                       |     100 |      100 |     100 |     100 |                       
  GreetingComponent.vue                             |     100 |      100 |     100 |     100 |                       
  Header.vue                                        |   87.17 |    88.23 |   66.66 |   87.17 | 30-37,134             
  OnetimeContribution.vue                           |     100 |      100 |     100 |     100 |                       
  PopupLink.vue                                     |     100 |      100 |     100 |     100 |                       
  RadioButtonInput.vue                              |   94.44 |      100 |      75 |   94.44 | 63                    
  RecurringContributionAnnualConversionForm.vue     |   93.02 |    78.04 |      70 |   93.02 | 19,50,217-245,262     
  RecurringContributionAnnualConversionSuccess.vue  |      96 |      100 |   83.33 |      96 | 17                    
  RecurringContributionCancelAltOptionContainer.vue |     100 |      100 |   83.33 |     100 |                       
  RecurringContributionCancelConfirmation.vue       |   97.22 |       90 |      90 |   97.22 | 22                    
  RecurringContributionCancelForm.vue               |   94.23 |    91.66 |   85.71 |   94.23 | 24,52,55              
  RecurringContributionCancelSuccess.vue            |   96.42 |       50 |     100 |   96.42 | 28                    
  RecurringContributionComponent.vue                |   89.23 |    88.88 |   88.88 |   89.23 | 42-45,51,56,184       
  RecurringContributionPauseForm.vue                |   97.14 |      100 |    87.5 |   97.14 | 22                    
  RecurringContributionPauseSuccess.vue             |   94.44 |      100 |      75 |   94.44 | 17                    
  RecurringContributionSummary.vue                  |     100 |      100 |     100 |     100 |                       
  RecurringContributionUpdateForm.vue               |   96.72 |    89.18 |   83.33 |   96.72 | 85,183                
  RecurringContributionUpdateSuccess.vue            |     100 |      100 |     100 |     100 |                       
  RelatedContentComponent.vue                       |   94.11 |      100 |      60 |   94.11 | 102-108               
 ext.donationInterface.donorPortal/views            |   96.31 |    81.66 |   97.22 |   96.25 |                       
  AmountDowngrade.vue                               |   97.61 |       70 |     100 |   97.56 | 31                    
  AnnualConversion.vue                              |    97.5 |       70 |     100 |   97.43 | 32                    
  CancelDonations.vue                               |   98.38 |    77.77 |     100 |   98.36 | 35                    
  Home.vue                                          |   96.77 |       90 |     100 |   96.77 | 38                    
  LoginView.vue                                     |      90 |    89.47 |   90.47 |      90 | 36-38,60-62,94,207    
  ManageDonations.vue                               |   98.07 |    91.66 |     100 |   98.03 | 21                    
  PauseDonations.vue                                |   97.61 |       70 |     100 |   97.56 | 29                    
  UpdateDonations.vue                               |   97.56 |       75 |     100 |    97.5 | 30                    
----------------------------------------------------|---------|----------|---------|---------|-----------------------

--- end ---
{}
{}
$ package-lock-lint /src/repo/package-lock.json
--- stdout ---
Checking /src/repo/package-lock.json

--- end ---
build: Updating dependencies

composer:
* mediawiki/mediawiki-codesniffer: 50.0.0 → 51.0.0

npm:
* eslint-config-wikimedia: 0.32.3 → 0.32.4


$ git add .
--- stdout ---

--- end ---
$ git commit -F /tmp/tmp_ijd7bnc
--- stdout ---
[master c83ec60] build: Updating dependencies
 3 files changed, 217 insertions(+), 344 deletions(-)

--- end ---
$ git format-patch HEAD~1 --stdout
--- stdout ---
From c83ec60c3005ae2fb7ef8ff4cc85823846266fa2 Mon Sep 17 00:00:00 2001
From: libraryupgrader <tools.libraryupgrader@tools.wmflabs.org>
Date: Wed, 6 May 2026 03:25:59 +0000
Subject: [PATCH] build: Updating dependencies
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

composer:
* mediawiki/mediawiki-codesniffer: 50.0.0 → 51.0.0

npm:
* eslint-config-wikimedia: 0.32.3 → 0.32.4

Change-Id: I1f9bec62f8f85923ee15d2d0c4203e0341f3ffce
---
 composer.json     |   2 +-
 package-lock.json | 557 ++++++++++++++++++----------------------------
 package.json      |   2 +-
 3 files changed, 217 insertions(+), 344 deletions(-)

diff --git a/composer.json b/composer.json
index 41e147c..f9750c5 100644
--- a/composer.json
+++ b/composer.json
@@ -34,7 +34,7 @@
 		"whichbrowser/parser": "^2.1"
 	},
 	"require-dev": {
-		"mediawiki/mediawiki-codesniffer": "50.0.0",
+		"mediawiki/mediawiki-codesniffer": "51.0.0",
 		"mediawiki/mediawiki-phan-config": "0.20.0",
 		"mediawiki/minus-x": "2.0.1",
 		"php-parallel-lint/php-console-highlighter": "1.0.0",
diff --git a/package-lock.json b/package-lock.json
index 93bd10c..bd127fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
 				"@wikimedia/codex": "2.4.0",
 				"@wikimedia/codex-icons": "2.4.0",
 				"babel-core": "^6.26.3",
-				"eslint-config-wikimedia": "0.32.3",
+				"eslint-config-wikimedia": "0.32.4",
 				"eslint-plugin-jest": "27.2.1",
 				"grunt": "1.6.2",
 				"grunt-banana-checker": "0.13.0",
@@ -1755,25 +1755,25 @@
 			}
 		},
 		"node_modules/@es-joy/jsdoccomment": {
-			"version": "0.76.0",
-			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz",
-			"integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==",
+			"version": "0.86.0",
+			"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+			"integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
 			"dev": true,
 			"dependencies": {
 				"@types/estree": "^1.0.8",
-				"@typescript-eslint/types": "^8.46.0",
-				"comment-parser": "1.4.1",
-				"esquery": "^1.6.0",
-				"jsdoc-type-pratt-parser": "~6.10.0"
+				"@typescript-eslint/types": "^8.58.0",
+				"comment-parser": "1.4.6",
+				"esquery": "^1.7.0",
+				"jsdoc-type-pratt-parser": "~7.2.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			}
 		},
 		"node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
-			"version": "8.48.1",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
-			"integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
+			"version": "8.59.2",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz",
+			"integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1811,9 +1811,9 @@
 			}
 		},
 		"node_modules/@eslint-community/regexpp": {
-			"version": "4.12.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
-			"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+			"version": "4.12.2",
+			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
 			"dev": true,
 			"engines": {
 				"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -2872,9 +2872,9 @@
 			"dev": true
 		},
 		"node_modules/@mdn/browser-compat-data": {
-			"version": "5.7.6",
-			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
-			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"version": "6.1.5",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-6.1.5.tgz",
+			"integrity": "sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==",
 			"dev": true
 		},
 		"node_modules/@nodelib/fs.scandir": {
@@ -3227,9 +3227,9 @@
 			}
 		},
 		"node_modules/@tootallnate/once": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
-			"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz",
+			"integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==",
 			"dev": true,
 			"engines": {
 				"node": ">= 10"
@@ -3871,9 +3871,9 @@
 			"dev": true
 		},
 		"node_modules/acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+			"version": "8.16.0",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+			"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
 			"dev": true,
 			"bin": {
 				"acorn": "bin/acorn"
@@ -4074,6 +4074,12 @@
 				"@mdn/browser-compat-data": "^5.6.19"
 			}
 		},
+		"node_modules/ast-metadata-inferer/node_modules/@mdn/browser-compat-data": {
+			"version": "5.7.6",
+			"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.7.6.tgz",
+			"integrity": "sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==",
+			"dev": true
+		},
 		"node_modules/astral-regex": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
@@ -4909,9 +4915,9 @@
 			}
 		},
 		"node_modules/comment-parser": {
-			"version": "1.4.1",
-			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
-			"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
+			"version": "1.4.6",
+			"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz",
+			"integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==",
 			"dev": true,
 			"engines": {
 				"node": ">= 12.0.0"
@@ -5578,13 +5584,13 @@
 			}
 		},
 		"node_modules/enhanced-resolve": {
-			"version": "5.18.3",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
-			"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
+			"version": "5.21.0",
+			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+			"integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
 			"dev": true,
 			"dependencies": {
 				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
+				"tapable": "^2.3.3"
 			},
 			"engines": {
 				"node": ">=10.13.0"
@@ -5798,51 +5804,52 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia": {
-			"version": "0.32.3",
-			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.3.tgz",
-			"integrity": "sha512-Ekz2/ozpCCjQl3VbC6dW7ChqoW7FRilLDxmJ+FJOZhIxxzZSZR5QqQOAGWSZAlG1ONkZbYV/TPwGLWZcrNxyaA==",
+			"version": "0.32.4",
+			"resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.32.4.tgz",
+			"integrity": "sha512-zcHJYss2vo8HK5PzkFuaV9mzaSGRuhA+jFGoQ4rNIwWz0usZsuQ2LYpkKxrbCVX1CbV0PzG+jJ6p0cLI+G37JQ==",
 			"dev": true,
 			"dependencies": {
 				"@stylistic/eslint-plugin": "^3.1.0",
-				"@typescript-eslint/eslint-plugin": "8.46.0",
-				"@typescript-eslint/parser": "8.46.0",
+				"@typescript-eslint/eslint-plugin": "8.54.0",
+				"@typescript-eslint/parser": "8.54.0",
 				"browserslist-config-wikimedia": "^0.7.0",
-				"eslint": "^8.57.0",
-				"eslint-plugin-compat": "^6.0.2",
+				"eslint-plugin-compat": "^6.1.0",
 				"eslint-plugin-es-x": "^8.7.0",
-				"eslint-plugin-jest": "^29.0.1",
-				"eslint-plugin-jsdoc": "61.3.0",
+				"eslint-plugin-jest": "^29.12.2",
+				"eslint-plugin-jsdoc": "^62.9.0",
 				"eslint-plugin-json-es": "^1.6.0",
-				"eslint-plugin-mediawiki": "^0.8.2",
+				"eslint-plugin-mediawiki": "^0.8.3",
 				"eslint-plugin-mocha": "^10.5.0",
-				"eslint-plugin-n": "^17.23.1",
-				"eslint-plugin-no-jquery": "^3.1.1",
-				"eslint-plugin-qunit": "^8.2.5",
-				"eslint-plugin-security": "^3.0.1",
+				"eslint-plugin-n": "^17.24.0",
+				"eslint-plugin-no-jquery": "^4.0.0",
+				"eslint-plugin-qunit": "^8.2.6",
+				"eslint-plugin-security": "^4.0.0",
 				"eslint-plugin-unicorn": "^56.0.1",
 				"eslint-plugin-vue": "^9.33.0",
-				"eslint-plugin-wdio": "^9.16.2",
+				"eslint-plugin-wdio": "9.23.0",
 				"eslint-plugin-yml": "^1.19.0"
 			},
 			"engines": {
 				"node": ">=20 <25"
+			},
+			"peerDependencies": {
+				"eslint": "^8.57.0"
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
-			"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
+			"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/regexpp": "^4.10.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/type-utils": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"graphemer": "^1.4.0",
-				"ignore": "^7.0.0",
+				"@eslint-community/regexpp": "^4.12.2",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/type-utils": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"ignore": "^7.0.5",
 				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.1.0"
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5852,22 +5859,22 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
-				"@typescript-eslint/parser": "^8.46.0",
+				"@typescript-eslint/parser": "^8.54.0",
 				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
-			"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/parser": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
+			"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/utils": "8.46.0",
-				"debug": "^4.3.4",
-				"ts-api-utils": "^2.1.0"
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5881,16 +5888,15 @@
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
-			"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/project-service": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
+			"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
 			"dev": true,
 			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0"
+				"@typescript-eslint/tsconfig-utils": "^8.54.0",
+				"@typescript-eslint/types": "^8.54.0",
+				"debug": "^4.4.3"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5900,21 +5906,17 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/parser": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
-			"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/scope-manager": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
+			"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/typescript-estree": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5922,22 +5924,13 @@
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/project-service": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
-			"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/tsconfig-utils": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
+			"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
 			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.0",
-				"@typescript-eslint/types": "^8.46.0",
-				"debug": "^4.3.4"
-			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
 			},
@@ -5949,14 +5942,17 @@
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
-			"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/type-utils": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
+			"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0"
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0",
+				"@typescript-eslint/utils": "8.54.0",
+				"debug": "^4.4.3",
+				"ts-api-utils": "^2.4.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5964,12 +5960,16 @@
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "^8.57.0 || ^9.0.0",
+				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
-			"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/types": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
+			"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
 			"dev": true,
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5977,40 +5977,45 @@
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/types": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
-			"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/typescript-estree": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
+			"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
 			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/project-service": "8.54.0",
+				"@typescript-eslint/tsconfig-utils": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/visitor-keys": "8.54.0",
+				"debug": "^4.4.3",
+				"minimatch": "^9.0.5",
+				"semver": "^7.7.3",
+				"tinyglobby": "^0.2.15",
+				"ts-api-utils": "^2.4.0"
+			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
 			},
 			"funding": {
 				"type": "opencollective",
 				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
-			"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/utils": {
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
+			"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/project-service": "8.46.0",
-				"@typescript-eslint/tsconfig-utils": "8.46.0",
-				"@typescript-eslint/types": "8.46.0",
-				"@typescript-eslint/visitor-keys": "8.46.0",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
+				"@eslint-community/eslint-utils": "^4.9.1",
+				"@typescript-eslint/scope-manager": "8.54.0",
+				"@typescript-eslint/types": "8.54.0",
+				"@typescript-eslint/typescript-estree": "8.54.0"
 			},
 			"engines": {
 				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6020,16 +6025,17 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			},
 			"peerDependencies": {
+				"eslint": "^8.57.0 || ^9.0.0",
 				"typescript": ">=4.8.4 <6.0.0"
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.46.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
-			"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+			"version": "8.54.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
+			"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "8.46.0",
+				"@typescript-eslint/types": "8.54.0",
 				"eslint-visitor-keys": "^4.2.1"
 			},
 			"engines": {
@@ -6041,9 +6047,9 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/brace-expansion": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
-			"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+			"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
 			"dev": true,
 			"dependencies": {
 				"balanced-match": "^1.0.0"
@@ -6078,141 +6084,6 @@
 				}
 			}
 		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/project-service": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz",
-			"integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.46.4",
-				"@typescript-eslint/types": "^8.46.4",
-				"debug": "^4.3.4"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz",
-			"integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/types": "8.46.4",
-				"@typescript-eslint/visitor-keys": "8.46.4"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz",
-			"integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==",
-			"dev": true,
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz",
-			"integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==",
-			"dev": true,
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz",
-			"integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/project-service": "8.46.4",
-				"@typescript-eslint/tsconfig-utils": "8.46.4",
-				"@typescript-eslint/types": "8.46.4",
-				"@typescript-eslint/visitor-keys": "8.46.4",
-				"debug": "^4.3.4",
-				"fast-glob": "^3.3.2",
-				"is-glob": "^4.0.3",
-				"minimatch": "^9.0.4",
-				"semver": "^7.6.0",
-				"ts-api-utils": "^2.1.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz",
-			"integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==",
-			"dev": true,
-			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.7.0",
-				"@typescript-eslint/scope-manager": "8.46.4",
-				"@typescript-eslint/types": "8.46.4",
-				"@typescript-eslint/typescript-estree": "8.46.4"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/eslint-config-wikimedia/node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.46.4",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz",
-			"integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==",
-			"dev": true,
-			"dependencies": {
-				"@typescript-eslint/types": "8.46.4",
-				"eslint-visitor-keys": "^4.2.1"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
 		"node_modules/eslint-config-wikimedia/node_modules/eslint-visitor-keys": {
 			"version": "4.2.1",
 			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
@@ -6250,9 +6121,9 @@
 			}
 		},
 		"node_modules/eslint-config-wikimedia/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6262,15 +6133,14 @@
 			}
 		},
 		"node_modules/eslint-plugin-compat": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz",
-			"integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==",
+			"version": "6.2.1",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.2.1.tgz",
+			"integrity": "sha512-gLKqUH+lQcCL+HzsROUjBDvakc5Zaga51Y4ZAkPCXc41pzKBfyluqTr2j8zOx8QQQb7zyglu1LVoL5aSNWf2SQ==",
 			"dev": true,
 			"dependencies": {
-				"@mdn/browser-compat-data": "^5.5.35",
+				"@mdn/browser-compat-data": "^6.1.1",
 				"ast-metadata-inferer": "^0.8.1",
-				"browserslist": "^4.24.2",
-				"caniuse-lite": "^1.0.30001687",
+				"browserslist": "^4.25.2",
 				"find-up": "^5.0.0",
 				"globals": "^15.7.0",
 				"lodash.memoize": "^4.1.2",
@@ -6280,7 +6150,7 @@
 				"node": ">=18.x"
 			},
 			"peerDependencies": {
-				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-compat/node_modules/find-up": {
@@ -6342,9 +6212,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-compat/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6399,31 +6269,31 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc": {
-			"version": "61.3.0",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.3.0.tgz",
-			"integrity": "sha512-E4m/5J5lrasd63Z74q4CCZ4PFnywnnrcvA7zZ98802NPhrZKKTp5NH+XAT+afcjXp2ps2/OQF5gPSWCT2XFCJg==",
+			"version": "62.9.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+			"integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
 			"dev": true,
 			"dependencies": {
-				"@es-joy/jsdoccomment": "~0.76.0",
+				"@es-joy/jsdoccomment": "~0.86.0",
 				"@es-joy/resolve.exports": "1.2.0",
 				"are-docs-informative": "^0.0.2",
-				"comment-parser": "1.4.1",
+				"comment-parser": "1.4.6",
 				"debug": "^4.4.3",
 				"escape-string-regexp": "^4.0.0",
-				"espree": "^10.4.0",
-				"esquery": "^1.6.0",
+				"espree": "^11.2.0",
+				"esquery": "^1.7.0",
 				"html-entities": "^2.6.0",
 				"object-deep-merge": "^2.0.0",
 				"parse-imports-exports": "^0.2.4",
-				"semver": "^7.7.3",
+				"semver": "^7.7.4",
 				"spdx-expression-parse": "^4.0.0",
 				"to-valid-identifier": "^1.0.0"
 			},
 			"engines": {
-				"node": ">=20.11.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"peerDependencies": {
-				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
+				"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
@@ -6439,38 +6309,38 @@
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": {
-			"version": "4.2.1",
-			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-			"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+			"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
 			"dev": true,
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/espree": {
-			"version": "10.4.0",
-			"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-			"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+			"version": "11.2.0",
+			"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+			"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
 			"dev": true,
 			"dependencies": {
-				"acorn": "^8.15.0",
+				"acorn": "^8.16.0",
 				"acorn-jsx": "^5.3.2",
-				"eslint-visitor-keys": "^4.2.1"
+				"eslint-visitor-keys": "^5.0.1"
 			},
 			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+				"node": "^20.19.0 || ^22.13.0 || >=24"
 			},
 			"funding": {
 				"url": "https://opencollective.com/eslint"
 			}
 		},
 		"node_modules/eslint-plugin-jsdoc/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6493,9 +6363,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-mediawiki": {
-			"version": "0.8.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.2.tgz",
-			"integrity": "sha512-ydYrpkzm8IVVDQA96QPF3HnFd2xjkIEh7gixD2gvOqUbUZF0p36LtpWXOFAlPWAvHLePWbNNTD5ovd3d4hEtog==",
+			"version": "0.8.3",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.8.3.tgz",
+			"integrity": "sha512-RQKZd40C1taMDk5N9+aFLEBGBB95RNG7Gc54EsJ8pHsJu8//nIdpxNFWPtQz6RNxz6pZUXBnMCxzkMOLM3Mm1w==",
 			"dev": true,
 			"dependencies": {
 				"upath": "^2.0.1"
@@ -6549,9 +6419,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n": {
-			"version": "17.23.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz",
-			"integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==",
+			"version": "17.24.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz",
+			"integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==",
 			"dev": true,
 			"dependencies": {
 				"@eslint-community/eslint-utils": "^4.5.0",
@@ -6623,9 +6493,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-n/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+			"version": "7.7.4",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+			"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
 			"dev": true,
 			"bin": {
 				"semver": "bin/semver.js"
@@ -6635,31 +6505,34 @@
 			}
 		},
 		"node_modules/eslint-plugin-no-jquery": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-3.1.1.tgz",
-			"integrity": "sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-4.0.0.tgz",
+			"integrity": "sha512-ZR631D3qIQfgjKOAcgvYa5cB8xdTvFXAD5MbK5x5WltLSwFxmGnoaTXNtnptFU7py07ALrIe5dZRYncu4RD/Ug==",
 			"dev": true,
 			"peerDependencies": {
-				"eslint": ">=8.0.0"
+				"eslint": ">=8.0.0 <9.0.0"
 			}
 		},
 		"node_modules/eslint-plugin-qunit": {
-			"version": "8.2.5",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.5.tgz",
-			"integrity": "sha512-qr7RJCYImKQjB+39q4q46i1l7p1V3joHzBE5CAYfxn5tfVFjrnjn/tw7q/kDyweU9kAIcLul0Dx/KWVUCb3BgA==",
+			"version": "8.2.6",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-8.2.6.tgz",
+			"integrity": "sha512-S1jC/DIW9J8VtNX4uG1vlf5FZVrfQFlcuiYmvTHR2IICUhubHqpWA5o+qS1tujh+81Gs39omKV2D4OXfbSJE5g==",
 			"dev": true,
 			"dependencies": {
-				"eslint-utils": "^3.0.0",
+				"@eslint-community/eslint-utils": "^4.4.0",
 				"requireindex": "^1.2.0"
 			},
 			"engines": {
 				"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
+			},
+			"peerDependencies": {
+				"eslint": ">=8.38.0"
 			}
 		},
 		"node_modules/eslint-plugin-security": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz",
-			"integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==",
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-4.0.0.tgz",
+			"integrity": "sha512-tfuQT8K/Li1ZxhFzyD8wPIKtlzZxqBcPr9q0jFMQ77wWAbKBVEhaMPVQRTMTvCMUDhwBe5vPVqQPwAGk/ASfxQ==",
 			"dev": true,
 			"dependencies": {
 				"safe-regex": "^2.1.1"
@@ -6790,9 +6663,9 @@
 			}
 		},
 		"node_modules/eslint-plugin-wdio": {
-			"version": "9.16.2",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.16.2.tgz",
-			"integrity": "sha512-qkqsPgxN70OnUPWMjmzJbSbvm2+Q087JIGss53/OFI4Y46xKlV5VLhLiYealaAibAiXmnfWKd0tERjZAzVL87A==",
+			"version": "9.23.0",
+			"resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-9.23.0.tgz",
+			"integrity": "sha512-8tcpupzp2Qmv+uSfhzeHi42LVA9PyjkpMBPclSIkPxBfXpj4fMrejwAHu1PROh1OmJN1VQcGQUTWvSzyRcV2vA==",
 			"dev": true,
 			"engines": {
 				"node": ">=18.20.0"
@@ -7123,9 +6996,9 @@
 			}
 		},
 		"node_modules/esquery": {
-			"version": "1.6.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
-			"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+			"version": "1.7.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
 			"dev": true,
 			"dependencies": {
 				"estraverse": "^5.1.0"
@@ -7625,9 +7498,9 @@
 			}
 		},
 		"node_modules/get-tsconfig": {
-			"version": "4.13.0",
-			"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
-			"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
+			"version": "4.14.0",
+			"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
+			"integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
 			"dev": true,
 			"dependencies": {
 				"resolve-pkg-maps": "^1.0.0"
@@ -10708,9 +10581,9 @@
 			}
 		},
 		"node_modules/jsdoc-type-pratt-parser": {
-			"version": "6.10.0",
-			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz",
-			"integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==",
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+			"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
 			"dev": true,
 			"engines": {
 				"node": ">=20.0.0"
@@ -13347,9 +13220,9 @@
 			"dev": true
 		},
 		"node_modules/tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+			"version": "2.3.3",
+			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+			"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
 			"dev": true,
 			"engines": {
 				"node": ">=6"
diff --git a/package.json b/package.json
index dcd2c0c..d684b0d 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
 		"@wikimedia/codex": "2.4.0",
 		"@wikimedia/codex-icons": "2.4.0",
 		"babel-core": "^6.26.3",
-		"eslint-config-wikimedia": "0.32.3",
+		"eslint-config-wikimedia": "0.32.4",
 		"eslint-plugin-jest": "27.2.1",
 		"grunt": "1.6.2",
 		"grunt-banana-checker": "0.13.0",
-- 
2.47.3


--- end ---
Source code is licensed under the AGPL.