mediawiki/skins/Vector: main (log #2358640)

sourcepatches

This run took 96 seconds.

$ date
--- stdout ---
Mon Feb 23 21:22:17 UTC 2026

--- end ---
$ git clone file:///srv/git/mediawiki-skins-Vector.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 ---
ea0363b9b0a1b9c29d6a36f19072e28c9cd57b3e refs/heads/master

--- end ---
$ /usr/bin/npm audit --json
--- stdout ---
{
  "auditReportVersion": 2,
  "vulnerabilities": {
    "@eslint/eslintrc": {
      "name": "@eslint/eslintrc",
      "severity": "high",
      "isDirect": false,
      "via": [
        "minimatch"
      ],
      "effects": [
        "eslint"
      ],
      "range": "0.0.1 || >=0.1.1",
      "nodes": [
        "node_modules/@eslint/eslintrc"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "@humanwhocodes/config-array": {
      "name": "@humanwhocodes/config-array",
      "severity": "high",
      "isDirect": false,
      "via": [
        "minimatch"
      ],
      "effects": [
        "eslint"
      ],
      "range": "*",
      "nodes": [
        "node_modules/@humanwhocodes/config-array"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "@jest/core": {
      "name": "@jest/core",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/reporters",
        "@jest/transform",
        "jest-config",
        "jest-resolve-dependencies",
        "jest-runner",
        "jest-runtime",
        "jest-snapshot",
        "rimraf"
      ],
      "effects": [
        "jest",
        "jest-cli"
      ],
      "range": "*",
      "nodes": [
        "node_modules/@jest/core"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "@jest/reporters": {
      "name": "@jest/reporters",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/transform",
        "glob"
      ],
      "effects": [
        "@jest/core"
      ],
      "range": "*",
      "nodes": [
        "node_modules/@jest/reporters"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "@jest/test-sequencer": {
      "name": "@jest/test-sequencer",
      "severity": "high",
      "isDirect": false,
      "via": [
        "jest-runtime"
      ],
      "effects": [
        "jest-config"
      ],
      "range": "<=28.0.0-alpha.11",
      "nodes": [
        "node_modules/@jest/test-sequencer"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "@jest/transform": {
      "name": "@jest/transform",
      "severity": "high",
      "isDirect": false,
      "via": [
        "babel-plugin-istanbul"
      ],
      "effects": [
        "babel-jest",
        "jest-runner",
        "jest-runtime",
        "jest-snapshot"
      ],
      "range": "*",
      "nodes": [
        "node_modules/@jest/transform"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    },
    "@stylistic/eslint-plugin": {
      "name": "@stylistic/eslint-plugin",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@typescript-eslint/utils"
      ],
      "effects": [],
      "range": "2.7.0-beta.0 - 5.0.0-beta.6 || >=6.0.0-beta.1",
      "nodes": [
        "node_modules/@stylistic/eslint-plugin"
      ],
      "fixAvailable": true
    },
    "@typescript-eslint/eslint-plugin": {
      "name": "@typescript-eslint/eslint-plugin",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@typescript-eslint/type-utils",
        "@typescript-eslint/utils",
        "eslint"
      ],
      "effects": [],
      "range": "<=8.55.1-alpha.3",
      "nodes": [
        "node_modules/@typescript-eslint/eslint-plugin"
      ],
      "fixAvailable": true
    },
    "@typescript-eslint/parser": {
      "name": "@typescript-eslint/parser",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@typescript-eslint/typescript-estree",
        "eslint"
      ],
      "effects": [
        "eslint-config-wikimedia"
      ],
      "range": "1.1.1-alpha.0 - 8.56.1-alpha.2",
      "nodes": [
        "node_modules/@typescript-eslint/parser"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "@typescript-eslint/type-utils": {
      "name": "@typescript-eslint/type-utils",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@typescript-eslint/typescript-estree",
        "@typescript-eslint/utils",
        "eslint"
      ],
      "effects": [
        "@typescript-eslint/eslint-plugin"
      ],
      "range": "5.9.2-alpha.0 - 8.56.1-alpha.2",
      "nodes": [
        "node_modules/@typescript-eslint/type-utils"
      ],
      "fixAvailable": true
    },
    "@typescript-eslint/typescript-estree": {
      "name": "@typescript-eslint/typescript-estree",
      "severity": "high",
      "isDirect": false,
      "via": [
        "minimatch"
      ],
      "effects": [
        "@typescript-eslint/parser",
        "@typescript-eslint/type-utils",
        "@typescript-eslint/utils"
      ],
      "range": "6.16.0 - 8.56.1-alpha.2",
      "nodes": [
        "node_modules/@typescript-eslint/typescript-estree",
        "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "@typescript-eslint/utils": {
      "name": "@typescript-eslint/utils",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@typescript-eslint/typescript-estree",
        "eslint"
      ],
      "effects": [
        "@stylistic/eslint-plugin",
        "@typescript-eslint/eslint-plugin",
        "@typescript-eslint/type-utils"
      ],
      "range": "<=8.56.1-alpha.2",
      "nodes": [
        "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils",
        "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils",
        "node_modules/@typescript-eslint/utils"
      ],
      "fixAvailable": true
    },
    "@vue/test-utils": {
      "name": "@vue/test-utils",
      "severity": "high",
      "isDirect": true,
      "via": [
        "js-beautify"
      ],
      "effects": [],
      "range": ">=2.4.1",
      "nodes": [
        "node_modules/@vue/test-utils"
      ],
      "fixAvailable": {
        "name": "@vue/test-utils",
        "version": "2.4.0",
        "isSemVerMajor": true
      }
    },
    "@vue/vue3-jest": {
      "name": "@vue/vue3-jest",
      "severity": "high",
      "isDirect": true,
      "via": [
        "babel-jest",
        "jest"
      ],
      "effects": [],
      "range": "*",
      "nodes": [
        "node_modules/@vue/vue3-jest"
      ],
      "fixAvailable": false
    },
    "@wikimedia/mw-node-qunit": {
      "name": "@wikimedia/mw-node-qunit",
      "severity": "high",
      "isDirect": true,
      "via": [
        "glob"
      ],
      "effects": [],
      "range": "*",
      "nodes": [
        "node_modules/@wikimedia/mw-node-qunit"
      ],
      "fixAvailable": false
    },
    "ajv": {
      "name": "ajv",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1113398,
          "name": "ajv",
          "dependency": "ajv",
          "title": "ajv has ReDoS when using `$data` option",
          "url": "https://github.com/advisories/GHSA-2g4f-4pwh-qvx6",
          "severity": "moderate",
          "cwe": [
            "CWE-400"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": "<6.14.0"
        },
        {
          "source": 1113399,
          "name": "ajv",
          "dependency": "ajv",
          "title": "ajv has ReDoS when using `$data` option",
          "url": "https://github.com/advisories/GHSA-2g4f-4pwh-qvx6",
          "severity": "moderate",
          "cwe": [
            "CWE-400"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": ">=7.0.0-alpha.0 <8.18.0"
        }
      ],
      "effects": [],
      "range": "<6.14.0 || >=7.0.0-alpha.0 <8.18.0",
      "nodes": [
        "node_modules/ajv",
        "node_modules/table/node_modules/ajv"
      ],
      "fixAvailable": true
    },
    "babel-jest": {
      "name": "babel-jest",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/transform",
        "babel-plugin-istanbul"
      ],
      "effects": [
        "@vue/vue3-jest",
        "jest-config",
        "ts-jest"
      ],
      "range": ">=24.0.0-alpha.0",
      "nodes": [
        "node_modules/babel-jest"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    },
    "babel-plugin-istanbul": {
      "name": "babel-plugin-istanbul",
      "severity": "high",
      "isDirect": false,
      "via": [
        "test-exclude"
      ],
      "effects": [
        "@jest/transform",
        "babel-jest"
      ],
      "range": ">=5.0.1",
      "nodes": [
        "node_modules/babel-plugin-istanbul"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    },
    "brace-expansion": {
      "name": "brace-expansion",
      "severity": "low",
      "isDirect": false,
      "via": [
        {
          "source": 1105443,
          "name": "brace-expansion",
          "dependency": "brace-expansion",
          "title": "brace-expansion Regular Expression Denial of Service vulnerability",
          "url": "https://github.com/advisories/GHSA-v6h2-p8h4-qcjw",
          "severity": "low",
          "cwe": [
            "CWE-400"
          ],
          "cvss": {
            "score": 3.1,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L"
          },
          "range": ">=1.0.0 <=1.1.11"
        },
        {
          "source": 1105444,
          "name": "brace-expansion",
          "dependency": "brace-expansion",
          "title": "brace-expansion Regular Expression Denial of Service vulnerability",
          "url": "https://github.com/advisories/GHSA-v6h2-p8h4-qcjw",
          "severity": "low",
          "cwe": [
            "CWE-400"
          ],
          "cvss": {
            "score": 3.1,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L"
          },
          "range": ">=2.0.0 <=2.0.1"
        }
      ],
      "effects": [],
      "range": "1.0.0 - 1.1.11 || 2.0.0 - 2.0.1",
      "nodes": [
        "node_modules/brace-expansion",
        "node_modules/editorconfig/node_modules/brace-expansion",
        "node_modules/js-beautify/node_modules/brace-expansion"
      ],
      "fixAvailable": true
    },
    "cross-spawn": {
      "name": "cross-spawn",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1104663,
          "name": "cross-spawn",
          "dependency": "cross-spawn",
          "title": "Regular Expression Denial of Service (ReDoS) in cross-spawn",
          "url": "https://github.com/advisories/GHSA-3xgq-45jj-v275",
          "severity": "high",
          "cwe": [
            "CWE-1333"
          ],
          "cvss": {
            "score": 7.5,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
          },
          "range": "<6.0.6"
        }
      ],
      "effects": [
        "pre-commit"
      ],
      "range": "<6.0.6",
      "nodes": [
        "node_modules/pre-commit/node_modules/cross-spawn"
      ],
      "fixAvailable": {
        "name": "pre-commit",
        "version": "1.0.10",
        "isSemVerMajor": true
      }
    },
    "diff": {
      "name": "diff",
      "severity": "low",
      "isDirect": false,
      "via": [
        {
          "source": 1112705,
          "name": "diff",
          "dependency": "diff",
          "title": "jsdiff has a Denial of Service vulnerability in parsePatch and applyPatch",
          "url": "https://github.com/advisories/GHSA-73rr-hh4g-fpgx",
          "severity": "low",
          "cwe": [
            "CWE-400",
            "CWE-1333"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": ">=5.0.0 <5.2.2"
        }
      ],
      "effects": [],
      "range": "5.0.0 - 5.2.1",
      "nodes": [
        "node_modules/diff"
      ],
      "fixAvailable": true
    },
    "doiuse": {
      "name": "doiuse",
      "severity": "high",
      "isDirect": false,
      "via": [
        "multimatch"
      ],
      "effects": [
        "stylelint-no-unsupported-browser-features"
      ],
      "range": ">=2.2.0",
      "nodes": [
        "node_modules/doiuse"
      ],
      "fixAvailable": {
        "name": "stylelint-config-wikimedia",
        "version": "0.10.1",
        "isSemVerMajor": true
      }
    },
    "editorconfig": {
      "name": "editorconfig",
      "severity": "high",
      "isDirect": false,
      "via": [
        "minimatch"
      ],
      "effects": [
        "js-beautify"
      ],
      "range": ">=1.0.0",
      "nodes": [
        "node_modules/editorconfig"
      ],
      "fixAvailable": {
        "name": "@vue/test-utils",
        "version": "2.4.0",
        "isSemVerMajor": true
      }
    },
    "eslint": {
      "name": "eslint",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@eslint/eslintrc",
        "@humanwhocodes/config-array",
        "file-entry-cache",
        "minimatch"
      ],
      "effects": [
        "@typescript-eslint/eslint-plugin",
        "@typescript-eslint/parser",
        "@typescript-eslint/type-utils",
        "@typescript-eslint/utils",
        "eslint-config-wikimedia",
        "eslint-plugin-jsdoc",
        "eslint-plugin-vue"
      ],
      "range": "0.7.1 - 2.0.0-rc.1 || 4.1.0 - 10.0.0-rc.2",
      "nodes": [
        "node_modules/eslint"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "eslint-config-wikimedia": {
      "name": "eslint-config-wikimedia",
      "severity": "high",
      "isDirect": true,
      "via": [
        "@stylistic/eslint-plugin",
        "@typescript-eslint/eslint-plugin",
        "@typescript-eslint/parser",
        "eslint",
        "eslint-plugin-jsdoc",
        "eslint-plugin-vue"
      ],
      "effects": [],
      "range": ">=0.9.0",
      "nodes": [
        "node_modules/eslint-config-wikimedia"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "eslint-plugin-jsdoc": {
      "name": "eslint-plugin-jsdoc",
      "severity": "high",
      "isDirect": false,
      "via": [
        "eslint"
      ],
      "effects": [
        "eslint-config-wikimedia"
      ],
      "range": "8.4.4 - 62.6.1",
      "nodes": [
        "node_modules/eslint-plugin-jsdoc"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "eslint-plugin-vue": {
      "name": "eslint-plugin-vue",
      "severity": "high",
      "isDirect": false,
      "via": [
        "eslint"
      ],
      "effects": [
        "eslint-config-wikimedia"
      ],
      "range": "5.0.0-beta.0 - 10.7.0",
      "nodes": [
        "node_modules/eslint-plugin-vue"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "file-entry-cache": {
      "name": "file-entry-cache",
      "severity": "high",
      "isDirect": false,
      "via": [
        "flat-cache"
      ],
      "effects": [
        "eslint"
      ],
      "range": "4.0.0 - 7.0.2",
      "nodes": [
        "node_modules/file-entry-cache"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "flat-cache": {
      "name": "flat-cache",
      "severity": "high",
      "isDirect": false,
      "via": [
        "rimraf"
      ],
      "effects": [
        "file-entry-cache"
      ],
      "range": "1.3.4 - 4.0.0",
      "nodes": [
        "node_modules/flat-cache"
      ],
      "fixAvailable": {
        "name": "eslint-config-wikimedia",
        "version": "0.8.1",
        "isSemVerMajor": true
      }
    },
    "form-data": {
      "name": "form-data",
      "severity": "critical",
      "isDirect": false,
      "via": [
        {
          "source": 1109538,
          "name": "form-data",
          "dependency": "form-data",
          "title": "form-data uses unsafe random function in form-data for choosing boundary",
          "url": "https://github.com/advisories/GHSA-fjxv-7rqg-78g4",
          "severity": "critical",
          "cwe": [
            "CWE-330"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": ">=4.0.0 <4.0.4"
        },
        {
          "source": 1109539,
          "name": "form-data",
          "dependency": "form-data",
          "title": "form-data uses unsafe random function in form-data for choosing boundary",
          "url": "https://github.com/advisories/GHSA-fjxv-7rqg-78g4",
          "severity": "critical",
          "cwe": [
            "CWE-330"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": ">=3.0.0 <3.0.4"
        }
      ],
      "effects": [],
      "range": "3.0.0 - 3.0.3 || 4.0.0 - 4.0.3",
      "nodes": [
        "node_modules/form-data",
        "node_modules/jest-environment-jsdom/node_modules/form-data"
      ],
      "fixAvailable": true
    },
    "glob": {
      "name": "glob",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1109842,
          "name": "glob",
          "dependency": "glob",
          "title": "glob CLI: Command injection via -c/--cmd executes matches with shell:true",
          "url": "https://github.com/advisories/GHSA-5j98-mcp5-4vw2",
          "severity": "high",
          "cwe": [
            "CWE-78"
          ],
          "cvss": {
            "score": 7.5,
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H"
          },
          "range": ">=10.2.0 <10.5.0"
        },
        "minimatch"
      ],
      "effects": [
        "@jest/reporters",
        "@wikimedia/mw-node-qunit",
        "jest-config",
        "jest-runtime",
        "rimraf",
        "test-exclude"
      ],
      "range": "3.0.0 - 10.5.0",
      "nodes": [
        "node_modules/glob",
        "node_modules/js-beautify/node_modules/glob"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    },
    "jest": {
      "name": "jest",
      "severity": "high",
      "isDirect": true,
      "via": [
        "@jest/core",
        "jest-cli"
      ],
      "effects": [
        "ts-jest"
      ],
      "range": ">=19.1.0-alpha.eed82034",
      "nodes": [
        "node_modules/jest"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-circus": {
      "name": "jest-circus",
      "severity": "high",
      "isDirect": false,
      "via": [
        "jest-runtime",
        "jest-snapshot"
      ],
      "effects": [
        "jest-config"
      ],
      "range": ">=25.2.4",
      "nodes": [
        "node_modules/jest-circus"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-cli": {
      "name": "jest-cli",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/core",
        "jest-config"
      ],
      "effects": [
        "jest"
      ],
      "range": ">=19.1.0-alpha.eed82034",
      "nodes": [
        "node_modules/jest-cli"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-config": {
      "name": "jest-config",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/test-sequencer",
        "babel-jest",
        "glob",
        "jest-circus",
        "jest-jasmine2",
        "jest-runner"
      ],
      "effects": [
        "jest-cli"
      ],
      "range": ">=19.1.0-alpha.eed82034",
      "nodes": [
        "node_modules/jest-config"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-jasmine2": {
      "name": "jest-jasmine2",
      "severity": "high",
      "isDirect": false,
      "via": [
        "jest-runtime",
        "jest-snapshot"
      ],
      "effects": [
        "jest-config"
      ],
      "range": ">=24.2.0-alpha.0",
      "nodes": [
        "node_modules/jest-jasmine2"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-resolve-dependencies": {
      "name": "jest-resolve-dependencies",
      "severity": "high",
      "isDirect": false,
      "via": [
        "jest-snapshot"
      ],
      "effects": [],
      "range": ">=27.0.0-next.0",
      "nodes": [
        "node_modules/jest-resolve-dependencies"
      ],
      "fixAvailable": true
    },
    "jest-runner": {
      "name": "jest-runner",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/transform",
        "jest-runtime"
      ],
      "effects": [
        "jest-config"
      ],
      "range": ">=24.0.0-alpha.0",
      "nodes": [
        "node_modules/jest-runner"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-runtime": {
      "name": "jest-runtime",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/transform",
        "glob",
        "jest-snapshot"
      ],
      "effects": [
        "@jest/test-sequencer",
        "jest-circus",
        "jest-jasmine2",
        "jest-runner"
      ],
      "range": ">=24.0.0-alpha.0",
      "nodes": [
        "node_modules/jest-runtime"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "jest-snapshot": {
      "name": "jest-snapshot",
      "severity": "high",
      "isDirect": false,
      "via": [
        "@jest/transform"
      ],
      "effects": [
        "@jest/core",
        "jest-circus",
        "jest-jasmine2",
        "jest-resolve-dependencies",
        "jest-runtime"
      ],
      "range": ">=27.0.0-next.0",
      "nodes": [
        "node_modules/jest-snapshot"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "js-beautify": {
      "name": "js-beautify",
      "severity": "high",
      "isDirect": false,
      "via": [
        "editorconfig"
      ],
      "effects": [
        "@vue/test-utils"
      ],
      "range": ">=1.14.9",
      "nodes": [
        "node_modules/js-beautify"
      ],
      "fixAvailable": {
        "name": "@vue/test-utils",
        "version": "2.4.0",
        "isSemVerMajor": true
      }
    },
    "js-yaml": {
      "name": "js-yaml",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1112714,
          "name": "js-yaml",
          "dependency": "js-yaml",
          "title": "js-yaml has prototype pollution in merge (<<)",
          "url": "https://github.com/advisories/GHSA-mh29-5h37-fv8m",
          "severity": "moderate",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 5.3,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
          },
          "range": "<3.14.2"
        },
        {
          "source": 1112715,
          "name": "js-yaml",
          "dependency": "js-yaml",
          "title": "js-yaml has prototype pollution in merge (<<)",
          "url": "https://github.com/advisories/GHSA-mh29-5h37-fv8m",
          "severity": "moderate",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 5.3,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
          },
          "range": ">=4.0.0 <4.1.1"
        }
      ],
      "effects": [],
      "range": "<3.14.2 || >=4.0.0 <4.1.1",
      "nodes": [
        "node_modules/@eslint/eslintrc/node_modules/js-yaml",
        "node_modules/cosmiconfig/node_modules/js-yaml",
        "node_modules/eslint/node_modules/js-yaml",
        "node_modules/js-yaml"
      ],
      "fixAvailable": true
    },
    "lodash": {
      "name": "lodash",
      "severity": "moderate",
      "isDirect": false,
      "via": [
        {
          "source": 1112455,
          "name": "lodash",
          "dependency": "lodash",
          "title": "Lodash has Prototype Pollution Vulnerability in `_.unset` and `_.omit` functions",
          "url": "https://github.com/advisories/GHSA-xxjr-mmjv-4gpg",
          "severity": "moderate",
          "cwe": [
            "CWE-1321"
          ],
          "cvss": {
            "score": 6.5,
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L"
          },
          "range": ">=4.0.0 <=4.17.22"
        }
      ],
      "effects": [],
      "range": "4.0.0 - 4.17.21",
      "nodes": [
        "node_modules/lodash"
      ],
      "fixAvailable": true
    },
    "minimatch": {
      "name": "minimatch",
      "severity": "high",
      "isDirect": false,
      "via": [
        {
          "source": 1113371,
          "name": "minimatch",
          "dependency": "minimatch",
          "title": "minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern",
          "url": "https://github.com/advisories/GHSA-3ppc-4f35-3m26",
          "severity": "high",
          "cwe": [
            "CWE-1333"
          ],
          "cvss": {
            "score": 0,
            "vectorString": null
          },
          "range": "<10.2.1"
        }
      ],
      "effects": [
        "@eslint/eslintrc",
        "@humanwhocodes/config-array",
        "@typescript-eslint/typescript-estree",
        "editorconfig",
        "eslint",
        "glob",
        "multimatch",
        "test-exclude"
      ],
      "range": "<10.2.1",
      "nodes": [
        "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch",
        "node_modules/@typescript-eslint/utils/node_modules/minimatch",
        "node_modules/editorconfig/node_modules/minimatch",
        "node_modules/js-beautify/node_modules/minimatch",
        "node_modules/minimatch"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    },
    "multimatch": {
      "name": "multimatch",
      "severity": "high",
      "isDirect": false,
      "via": [
        "minimatch"
      ],
      "effects": [
        "doiuse"
      ],
      "range": "<=7.0.0",
      "nodes": [
        "node_modules/multimatch"
      ],
      "fixAvailable": {
        "name": "stylelint-config-wikimedia",
        "version": "0.10.1",
        "isSemVerMajor": true
      }
    },
    "pre-commit": {
      "name": "pre-commit",
      "severity": "high",
      "isDirect": true,
      "via": [
        "cross-spawn"
      ],
      "effects": [],
      "range": ">=1.1.0",
      "nodes": [
        "node_modules/pre-commit"
      ],
      "fixAvailable": {
        "name": "pre-commit",
        "version": "1.0.10",
        "isSemVerMajor": true
      }
    },
    "rimraf": {
      "name": "rimraf",
      "severity": "high",
      "isDirect": false,
      "via": [
        "glob"
      ],
      "effects": [
        "@jest/core",
        "flat-cache"
      ],
      "range": "2.3.0 - 3.0.2 || 4.2.0 - 5.0.10",
      "nodes": [
        "node_modules/rimraf"
      ],
      "fixAvailable": {
        "name": "jest",
        "version": "25.0.0",
        "isSemVerMajor": true
      }
    },
    "stylelint-config-wikimedia": {
      "name": "stylelint-config-wikimedia",
      "severity": "high",
      "isDirect": true,
      "via": [
        "stylelint-no-unsupported-browser-features"
      ],
      "effects": [],
      "range": ">=0.10.2",
      "nodes": [
        "node_modules/stylelint-config-wikimedia"
      ],
      "fixAvailable": {
        "name": "stylelint-config-wikimedia",
        "version": "0.10.1",
        "isSemVerMajor": true
      }
    },
    "stylelint-no-unsupported-browser-features": {
      "name": "stylelint-no-unsupported-browser-features",
      "severity": "high",
      "isDirect": false,
      "via": [
        "doiuse"
      ],
      "effects": [
        "stylelint-config-wikimedia"
      ],
      "range": "*",
      "nodes": [
        "node_modules/stylelint-no-unsupported-browser-features"
      ],
      "fixAvailable": {
        "name": "stylelint-config-wikimedia",
        "version": "0.10.1",
        "isSemVerMajor": true
      }
    },
    "test-exclude": {
      "name": "test-exclude",
      "severity": "high",
      "isDirect": false,
      "via": [
        "glob",
        "minimatch"
      ],
      "effects": [
        "babel-plugin-istanbul"
      ],
      "range": "4.2.2 || 5.0.0 - 7.0.2",
      "nodes": [
        "node_modules/test-exclude"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    },
    "ts-jest": {
      "name": "ts-jest",
      "severity": "high",
      "isDirect": true,
      "via": [
        "babel-jest",
        "jest"
      ],
      "effects": [],
      "range": ">=25.10.0-alpha.1",
      "nodes": [
        "node_modules/ts-jest"
      ],
      "fixAvailable": {
        "name": "ts-jest",
        "version": "27.0.3",
        "isSemVerMajor": true
      }
    }
  },
  "metadata": {
    "vulnerabilities": {
      "info": 0,
      "low": 2,
      "moderate": 3,
      "high": 45,
      "critical": 1,
      "total": 51
    },
    "dependencies": {
      "prod": 1,
      "dev": 969,
      "optional": 3,
      "peer": 0,
      "peerOptional": 0,
      "total": 969
    }
  }
}

--- 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: 39 installs, 0 updates, 0 removals
  - Locking composer/installers (v2.3.0)
  - Locking composer/pcre (3.3.2)
  - Locking composer/semver (3.4.4)
  - Locking composer/spdx-licenses (1.5.9)
  - Locking composer/xdebug-handler (3.0.5)
  - Locking dealerdirect/phpcodesniffer-composer-installer (v1.2.0)
  - Locking doctrine/deprecations (1.1.6)
  - Locking felixfbecker/advanced-json-rpc (v3.2.1)
  - Locking mediawiki/mediawiki-codesniffer (v48.0.0)
  - Locking mediawiki/mediawiki-phan-config (0.18.0)
  - Locking mediawiki/minus-x (1.1.3)
  - Locking mediawiki/phan-taint-check-plugin (8.0.0)
  - Locking microsoft/tolerant-php-parser (v0.1.2)
  - Locking netresearch/jsonmapper (v4.5.0)
  - Locking phan/phan (5.5.2)
  - 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.1.1)
  - Locking phpdocumentor/reflection-common (2.2.0)
  - Locking phpdocumentor/reflection-docblock (5.6.6)
  - Locking phpdocumentor/type-resolver (1.12.0)
  - Locking phpstan/phpdoc-parser (2.3.2)
  - Locking psr/container (2.0.2)
  - Locking psr/log (3.0.2)
  - Locking sabre/event (5.1.7)
  - Locking squizlabs/php_codesniffer (3.13.2)
  - Locking symfony/console (v7.4.4)
  - Locking symfony/deprecation-contracts (v3.6.0)
  - Locking symfony/polyfill-ctype (v1.33.0)
  - Locking symfony/polyfill-intl-grapheme (v1.33.0)
  - Locking symfony/polyfill-intl-normalizer (v1.33.0)
  - Locking symfony/polyfill-mbstring (v1.33.0)
  - Locking symfony/polyfill-php80 (v1.33.0)
  - Locking symfony/service-contracts (v3.6.1)
  - Locking symfony/string (v8.0.4)
  - Locking tysonandre/var_representation_polyfill (0.1.3)
  - Locking webmozart/assert (2.1.5)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 39 installs, 0 updates, 0 removals
    0 [>---------------------------]    0 [->--------------------------]
  - Installing composer/installers (v2.3.0): Extracting archive
  - Installing squizlabs/php_codesniffer (3.13.2): Extracting archive
  - Installing dealerdirect/phpcodesniffer-composer-installer (v1.2.0): Extracting archive
  - Installing composer/pcre (3.3.2): Extracting archive
  - Installing phpcsstandards/phpcsutils (1.1.1): Extracting archive
  - Installing phpcsstandards/phpcsextra (1.4.0): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.33.0): Extracting archive
  - Installing composer/spdx-licenses (1.5.9): Extracting archive
  - Installing composer/semver (3.4.4): Extracting archive
  - Installing mediawiki/mediawiki-codesniffer (v48.0.0): Extracting archive
  - Installing tysonandre/var_representation_polyfill (0.1.3): Extracting archive
  - Installing symfony/polyfill-php80 (v1.33.0): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.33.0): Extracting archive
  - Installing symfony/polyfill-intl-grapheme (v1.33.0): Extracting archive
  - Installing symfony/polyfill-ctype (v1.33.0): Extracting archive
  - Installing symfony/string (v8.0.4): Extracting archive
  - Installing symfony/deprecation-contracts (v3.6.0): Extracting archive
  - Installing psr/container (2.0.2): Extracting archive
  - Installing symfony/service-contracts (v3.6.1): Extracting archive
  - Installing symfony/console (v7.4.4): Extracting archive
  - Installing sabre/event (5.1.7): Extracting archive
  - Installing netresearch/jsonmapper (v4.5.0): Extracting archive
  - Installing microsoft/tolerant-php-parser (v0.1.2): Extracting archive
  - Installing webmozart/assert (2.1.5): 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 (1.12.0): Extracting archive
  - Installing phpdocumentor/reflection-docblock (5.6.6): Extracting archive
  - Installing felixfbecker/advanced-json-rpc (v3.2.1): Extracting archive
  - Installing psr/log (3.0.2): Extracting archive
  - Installing composer/xdebug-handler (3.0.5): Extracting archive
  - Installing phan/phan (5.5.2): Extracting archive
  - Installing mediawiki/phan-taint-check-plugin (8.0.0): Extracting archive
  - Installing mediawiki/mediawiki-phan-config (0.18.0): Extracting archive
  - Installing mediawiki/minus-x (1.1.3): 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
  0/36 [>---------------------------]   0%
 28/36 [=====================>------]  77%
 35/36 [===========================>]  97%
 36/36 [============================] 100%
1 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
18 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:jest from 27.4.7 -> 29.7.0
Upgrading n:@vue/vue3-jest from 27.0.0 -> 29.2.6
Upgrading n:@wikimedia/codex from 2.3.1 -> 2.3.4
Upgrading n:@wikimedia/codex-icons from 2.3.1 -> 2.3.4
Upgrading n:ts-jest from 27.1.5 -> 29.2.5
$ /usr/bin/npm install
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.3.4',
npm WARN EBADENGINE   required: { npm: '>=10.8.2', node: '>=20.19.1' },
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.3.4',
npm WARN EBADENGINE   required: { npm: '>=10.8.2', node: '>=20.19.1' },
npm WARN EBADENGINE   current: { node: 'v20.19.2', npm: '9.2.0' }
npm WARN EBADENGINE }
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 lodash.get@4.4.2: This package is deprecated. Use the optional chaining (?.) operator instead.
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 glob@7.2.0: Glob versions prior to v9 are no longer supported
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated domexception@4.0.0: Use your platform's native DOMException instead
npm WARN deprecated mkdirp@0.3.0: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
npm WARN deprecated sinon@12.0.1: 16.1.1
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
--- stdout ---

added 991 packages, and audited 992 packages in 21s

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

52 vulnerabilities (2 low, 3 moderate, 46 high, 1 critical)

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

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

Some issues need review, and may require choosing
a different dependency.

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 jest-environment-jsdom@29.7.0 --save-dev --save-exact
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.3.4',
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.3.4',
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 14 packages, and audited 1006 packages in 5s

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

52 vulnerabilities (2 low, 3 moderate, 46 high, 1 critical)

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

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

Some issues need review, and may require choosing
a different dependency.

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 ci
--- stderr ---
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@wikimedia/codex@2.3.4',
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.3.4',
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 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 lodash.get@4.4.2: This package is deprecated. Use the optional chaining (?.) operator instead.
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 glob@7.2.0: Glob versions prior to v9 are no longer supported
npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm WARN deprecated domexception@4.0.0: Use your platform's native DOMException instead
npm WARN deprecated mkdirp@0.3.0: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
npm WARN deprecated sinon@12.0.1: 16.1.1
npm WARN deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.
--- stdout ---

added 1005 packages, and audited 1006 packages in 18s

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

52 vulnerabilities (2 low, 3 moderate, 46 high, 1 critical)

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

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

Some issues need review, and may require choosing
a different dependency.

Run `npm audit` for details.

--- end ---
$ /usr/bin/npm test
--- stderr ---
resources/skins.vector.clientPreferences/clientPreferences.less
  25:1  ⚠  Unexpected browser feature "prefers-color-scheme" is not supported by Safari 12,11.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5  plugin/no-unsupported-browser-features

resources/skins.vector.js/bottomDock.less
  12:2  ⚠  Unexpected browser feature "flexbox-gap" is not supported by Safari 12,13,14,11.1,12.1,13.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4  plugin/no-unsupported-browser-features

resources/skins.vector.legacy.js/bottomDock.less
  10:2  ⚠  Unexpected browser feature "flexbox-gap" is not supported by Safari 12,13,14,11.1,12.1,13.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4  plugin/no-unsupported-browser-features

resources/skins.vector.styles/CSSCustomProperties.less
  143:1  ⚠  Unexpected browser feature "prefers-color-scheme" is not supported by Safari 12,11.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5  plugin/no-unsupported-browser-features

resources/skins.vector.styles/variables.less
   45:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
   45:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  137:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  137:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  138:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  139:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  139:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  140:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  140:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  141:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  141:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  152:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features

resources/skins.vector.styles.legacy/variables.less
   61:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
   61:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  144:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  144:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  145:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  146:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  146:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  147:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  147:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  148:1  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  148:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  154:1  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features

resources/skins.vector.styles/components/Indicators.less
  1:1  ⚠  Unexpected browser feature "flexbox-gap" is not supported by Safari 12,13,14,11.1,12.1,13.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4  plugin/no-unsupported-browser-features

resources/skins.vector.styles/components/PinnableElement.less
  28:2  ⚠  Unexpected browser feature "css-containment" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3  plugin/no-unsupported-browser-features

resources/skins.vector.styles/layouts/grid.less
   23:3  ⚠  Unexpected browser feature "css-overflow-anchor" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1,18.2,18.3,18.4,18.5-18.6,26.0,26.1,26.2,26.3, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1,18.2,18.3,18.4,18.5-18.7,26.0,26.1,26.2,26.3  plugin/no-unsupported-browser-features
  121:4  ⚠  Unexpected browser feature "css-overflow-anchor" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1,18.2,18.3,18.4,18.5-18.6,26.0,26.1,26.2,26.3, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1,18.2,18.3,18.4,18.5-18.7,26.0,26.1,26.2,26.3  plugin/no-unsupported-browser-features

resources/skins.vector.styles/layouts/screen.less
  128:2  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  128:2  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  173:2  ⚠  Unexpected browser feature "css-container-queries" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8                                                                                                                                                                                           plugin/no-unsupported-browser-features
  173:2  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  191:2  ⚠  Unexpected browser feature "css-touch-action" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1,18.2,18.3,18.4,18.5-18.6,26.0,26.1,26.2,26.3                                                                                                                                                                                                          plugin/no-unsupported-browser-features
  191:2  ⚠  Unexpected browser feature "pointer" is not supported by Safari 12,11.1,12.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5                                                                                                                                                                                                                                                                                                                                                    plugin/no-unsupported-browser-features

resources/skins.vector.styles/layouts/toc/unpinned.less
  42:4  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features
  61:5  ⚠  Unexpected browser feature "css-paged-media" is not supported by Safari 12,13,14,15,11.1,12.1,13.1,14.1,15.1,15.2-15.3,15.4,15.5,15.6,16.0,16.1,16.2,16.3,16.4,16.5,16.6,17.0,17.1,17.2,17.3,17.4,17.5,17.6,18.0,18.1, Safari on iOS 11.3-11.4,12.0-12.1,12.2-12.5,13.0-13.1,13.2,13.3,13.4-13.7,14.0-14.4,14.5-14.8,15.0-15.1,15.2-15.3,15.4,15.5,15.6-15.8,16.0,16.1,16.2,16.3,16.4,16.5,16.6-16.7,17.0,17.1,17.2,17.3,17.4,17.5,17.6-17.7,18.0,18.1, Android Browser 144  plugin/no-unsupported-browser-features

⚠ 40 problems (0 errors, 40 warnings)

FAIL tests/jest/tableOfContents.test.js
  ● Test suite failed to run

    ● Invalid return value:
      `process()` or/and `processAsync()` method of code transformer found at 
      "/src/repo/node_modules/mustache-jest/index.js" 
      should return an object or a Promise resolving to an object. The object 
      must have `code` property with a string of processed code.
      This error may be caused by a breaking change in Jest 28:
      https://jestjs.io/docs/28.x/upgrading-to-jest28#transformer
      Code Transformation Documentation:
      https://jestjs.io/docs/code-transformation

      4 |  * TableOfContents Mustache templates
      5 |  */
    > 6 | const templateTocContents = require( /** @type {string} */ ( './templates/TableOfContents__list.mustache' ) );
        |                             ^
      7 | const templateTocLine = require( /** @type {string} */ ( './templates/TableOfContents__line.mustache' ) );
      8 | /**
      9 |  * TableOfContents Config object for filling mustache templates

      at ScriptTransformer._buildTransformResult (node_modules/@jest/transform/build/ScriptTransformer.js:442:15)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:554:17)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:674:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:726:19)
      at Object.require (resources/skins.vector.js/tableOfContents.js:6:29)
      at Object.<anonymous> (tests/jest/tableOfContents.test.js:9:29)

FAIL tests/jest/skins.vector.js/dropdownMenus.test.js
  ● addPortletLinkHandler › Adds a span with icon class to menus

    expect(received).toMatchSnapshot()

    Snapshot name: `addPortletLinkHandler Adds a span with icon class to menus 1`

    - Snapshot  - 3
    + Received  + 3

    @@ -1,9 +1,9 @@
      "
    - 		<ul class=\"vector-menu\">
    + 		<ul class="vector-menu">
    - 			<li class=\"mw-list-item mw-list-item-js\" id=\"test-id\">
    + 			<li class="mw-list-item mw-list-item-js" id="test-id">
    - 				<a href=\"#test-href\">
    + 				<a href="#test-href">
      					<span>
      						test link content
      					</span>
      				</a>
      			</li>

      53 | 		const mockPortletItem = document.getElementById( 'test-id' );
      54 | 		addPortletLinkHandler( mockPortletItem, { id: 'test-id' } );
    > 55 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      56 | 	} );
      57 |
      58 | 	test( 'Does not add an icon when noicon class is present', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/dropdownMenus.test.js:55:37)

  ● addPortletLinkHandler › Does not add an icon when noicon class is present

    expect(received).toMatchSnapshot()

    Snapshot name: `addPortletLinkHandler Does not add an icon when noicon class is present 1`

    - Snapshot  - 3
    + Received  + 3

    @@ -1,9 +1,9 @@
      "
    - 		<ul class=\"vector-menu\">
    + 		<ul class="vector-menu">
    - 			<li class=\"mw-list-item mw-list-item-js\" id=\"test-id\">
    + 			<li class="mw-list-item mw-list-item-js" id="test-id">
    - 				<a href=\"#test-href\">
    + 				<a href="#test-href">
      					<span>
      						test link content
      					</span>
      				</a>
      			</li>

      72 | 		const mockPortletItem = document.getElementById( 'test-id' );
      73 | 		addPortletLinkHandler( mockPortletItem, { id: 'test-id' } );
    > 74 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      75 | 	} );
      76 |
      77 | 	test( 'JS portlet should be moved to more menu (#p-cactions) at narrow widths', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/dropdownMenus.test.js:74:37)

 › 2 snapshots failed.
FAIL tests/jest/pinnableElement.test.js
  ● Pinnable header › renders

    expect(received).toMatchSnapshot()

    Snapshot name: `Pinnable header renders 1`

    - Snapshot  - 11
    + Received  + 11

    @@ -1,19 +1,19 @@
    - "<div id=\"pinned-container\">
    + "<div id="pinned-container">
      			
      		</div>
    - 		<div class=\"vector-dropdown\">
    + 		<div class="vector-dropdown">
    - 			<input type=\"checkbox\" id=\"checkbox\" class=\"vector-menu-checkbox\">
    + 			<input type="checkbox" id="checkbox" class="vector-menu-checkbox">
    - 			<label for=\"checkbox\" class=\"vector-menu-heading \">
    + 			<label for="checkbox" class="vector-menu-heading ">
    - 				<span class=\"vector-menu-heading-label\">Dropdown</span>
    + 				<span class="vector-menu-heading-label">Dropdown</span>
      			</label>
    - 			<div class=\"vector-menu-content\">
    + 			<div class="vector-menu-content">
    - 				<div id=\"unpinned-container\">
    + 				<div id="unpinned-container">
    - 				<div id=\"pinnable-element\"><div class=\"vector-pinnable-header pinnable-element-pinnable-header vector-pinnable-header-unpinned\" data-feature-name=\"pinned\" data-pinnable-element-id=\"pinnable-element\">
    + 				<div id="pinnable-element"><div class="vector-pinnable-header pinnable-element-pinnable-header vector-pinnable-header-unpinned" data-feature-name="pinned" data-pinnable-element-id="pinnable-element">
    - 	<div class=\"vector-pinnable-header-label\">simple pinnable element</div>
    + 	<div class="vector-pinnable-header-label">simple pinnable element</div>
    - 	<button class=\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\" data-event-name=\"pinnable-header.pinnable-element.pin\">pin</button>
    + 	<button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.pinnable-element.pin">pin</button>
    - 	<button class=\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\" data-event-name=\"pinnable-header.pinnable-element.unpin\">unpin</button>
    + 	<button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.pinnable-element.unpin">unpin</button>
      </div>
      </div>
      				</div>
      			</div>
      		</div>

      71 | 	test( 'renders', () => {
      72 | 		initializeHTML( simpleData );
    > 73 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      74 | 	} );
      75 |
      76 | 	test( 'updates pinnable header classes when toggle is pressed', () => {

      at Object.<anonymous> (tests/jest/pinnableElement.test.js:73:37)

 › 1 snapshot failed.
PASS tests/jest/features.test.js
PASS tests/jest/skins.vector.js/disableNightModeIfGadget.test.js
PASS tests/jest/skins.vector.legacy.js/portlets.test.js
FAIL tests/jest/skins.vector.es6/main.test.js
  ● Test suite failed to run

    ● Invalid return value:
      `process()` or/and `processAsync()` method of code transformer found at 
      "/src/repo/node_modules/mustache-jest/index.js" 
      should return an object or a Promise resolving to an object. The object 
      must have `code` property with a string of processed code.
      This error may be caused by a breaking change in Jest 28:
      https://jestjs.io/docs/28.x/upgrading-to-jest28#transformer
      Code Transformation Documentation:
      https://jestjs.io/docs/code-transformation

      4 |  * TableOfContents Mustache templates
      5 |  */
    > 6 | const templateTocContents = require( /** @type {string} */ ( './templates/TableOfContents__list.mustache' ) );
        |                             ^
      7 | const templateTocLine = require( /** @type {string} */ ( './templates/TableOfContents__line.mustache' ) );
      8 | /**
      9 |  * TableOfContents Config object for filling mustache templates

      at ScriptTransformer._buildTransformResult (node_modules/@jest/transform/build/ScriptTransformer.js:442:15)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:554:17)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:674:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:726:19)
      at Object.require (resources/skins.vector.js/tableOfContents.js:6:29)
      at Object.require (resources/skins.vector.js/setupIntersectionObservers.js:6:24)
      at Object.<anonymous> (tests/jest/skins.vector.es6/main.test.js:8:18)

FAIL tests/jest/skins.vector.js/tables.test.js
  ● tables › wraps table with div

    expect(received).toMatchSnapshot()

    Snapshot name: `tables wraps table with div 1`

    - Snapshot  - 2
    + Received  + 2

      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
    - 				<div class=\"noresize\"><table class=\"wikitable\">
    + 				<div class="noresize"><table class="wikitable">
      					<tbody><tr><th>table table table</th></tr></tbody>
      				</table></div>
      			</div>
      		"

      12 | 		tables();
      13 |
    > 14 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      15 | 	} );
      16 |
      17 | 	test( 'wraps multiple table with div', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:14:37)

  ● tables › wraps multiple table with div

    expect(received).toMatchSnapshot()

    Snapshot name: `tables wraps multiple table with div 1`

    - Snapshot  - 5
    + Received  + 5

      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
    - 				<div class=\"noresize\"><table class=\"wikitable\">
    + 				<div class="noresize"><table class="wikitable">
      					<tbody><tr><th>table table table</th></tr></tbody>
      				</table></div>
    - 				<div class=\"noresize\"><table class=\"wikitable\">
    + 				<div class="noresize"><table class="wikitable">
    - 				</table></div><div class=\"noresize\"><table class=\"wikitable\">
    + 				</table></div><div class="noresize"><table class="wikitable">
      					<tbody><tr><th>table table table</th></tr></tbody>
      				</table></div>
    - 				<div class=\"noresize\"><table class=\"wikitable\">
    + 				<div class="noresize"><table class="wikitable">
      					<tbody><tr><th>table table table</th></tr></tbody>
      				</table></div>
      			</div>
      		"

      32 | 		tables();
      33 |
    > 34 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      35 | 	} );
      36 |
      37 | 	test( 'doesnt wrap nested tables', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:34:37)

  ● tables › doesnt wrap nested tables

    expect(received).toMatchSnapshot()

    Snapshot name: `tables doesnt wrap nested tables 1`

    - Snapshot  - 3
    + Received  + 3

      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
    - 				<div class=\"noresize\"><table class=\"wikitable\">
    + 				<div class="noresize"><table class="wikitable">
      					<tbody>
      						<tr><th>table table table</th></tr>
    - 						<tr><td><table class=\"wikitable\"><tbody><tr><th>table table table</th></tr></tbody></table></td><td></td></tr>
    + 						<tr><td><table class="wikitable"><tbody><tr><th>table table table</th></tr></tbody></table></td><td></td></tr>
      					</tbody>
      				</table></div>
      			</div>
      		"

      48 | 		tables();
      49 |
    > 50 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      51 | 	} );
      52 |
      53 | 	test( 'doesnt wrap tables that are not wikitables', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:50:37)

  ● tables › doesnt wrap tables that are not wikitables

    expect(received).toMatchSnapshot()

    Snapshot name: `tables doesnt wrap tables that are not wikitables 1`

    - Snapshot  - 1
    + Received  + 1

    @@ -1,7 +1,7 @@
      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
      				<table>
      					<tbody>
      						<tr><th>table table table</th></tr>
      						<tr><td><table><tbody><tr><th>table table table</th></tr></tbody></table></td><td></td></tr>
      					</tbody>

      64 | 		tables();
      65 |
    > 66 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      67 | 	} );
      68 |
      69 | 	test( 'doesnt wrap tables that already have noresize', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:66:37)

  ● tables › doesnt wrap tables that already have noresize

    expect(received).toMatchSnapshot()

    Snapshot name: `tables doesnt wrap tables that already have noresize 1`

    - Snapshot  - 3
    + Received  + 3

    @@ -1,9 +1,9 @@
      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
    - 				<div class=\"noresize\">
    + 				<div class="noresize">
    - 					<table class=\"wikitable\">
    + 					<table class="wikitable">
      						<tbody>
      							<tr><th>table table table</th></tr>
      						</tbody>
      					</table>
      				</div>

      81 | 		tables();
      82 |
    > 83 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      84 | 	} );
      85 |
      86 | 	test( 'doesnt wrap tables that are already wrapped', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:83:37)

  ● tables › doesnt wrap tables that are already wrapped

    expect(received).toMatchSnapshot()

    Snapshot name: `tables doesnt wrap tables that are already wrapped 1`

    - Snapshot  - 2
    + Received  + 2

    @@ -1,9 +1,9 @@
      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
      				<div>
    - 					<table class=\"wikitable\">
    + 					<table class="wikitable">
      						<tbody>
      							<tr><th>table table table</th></tr>
      						</tbody>
      					</table>
      				</div>

       98 | 		tables();
       99 |
    > 100 | 		expect( document.body.innerHTML ).toMatchSnapshot();
          | 		                                  ^
      101 | 	} );
      102 |
      103 | 	test( 'doesnt wrap floated tables', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:100:37)

  ● tables › doesnt wrap floated tables

    expect(received).toMatchSnapshot()

    Snapshot name: `tables doesnt wrap floated tables 1`

    - Snapshot  - 2
    + Received  + 2

    @@ -1,8 +1,8 @@
      "
    - 			<div class=\"mw-parser-output\">
    + 			<div class="mw-parser-output">
    - 				<table class=\"wikitable\" style=\"float:right\">
    + 				<table class="wikitable" style="float:right">
      					<tbody>
      						<tr><th>table table table</th></tr>
      					</tbody>
      				</table>
      			<div>

      113 | 		tables();
      114 |
    > 115 | 		expect( document.body.innerHTML ).toMatchSnapshot();
          | 		                                  ^
      116 | 	} );
      117 | } );
      118 |

      at Object.<anonymous> (tests/jest/skins.vector.js/tables.test.js:115:37)

 › 7 snapshots failed.
FAIL tests/jest/stickyHeader.test.js
  ● Sticky header renders

    expect(received).toMatchSnapshot()

    Snapshot name: `Sticky header renders 1`

    - Snapshot  - 23
    + Received  + 23

    - "<div id=\"vector-sticky-header\" class=\"vector-sticky-header\">
    + "<div id="vector-sticky-header" class="vector-sticky-header">
    - 	<div class=\"vector-sticky-header-start\">
    + 	<div class="vector-sticky-header-start">
    - 		<div class=\"vector-sticky-header-icon-start vector-button-flush-left\" aria-hidden=\"true\">
    + 		<div class="vector-sticky-header-icon-start vector-button-flush-left" aria-hidden="true">
    - <button class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-sticky-header-search-toggle\" data-event-name=\"ui.vector-sticky-search-form.icon\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-search mw-ui-icon-wikimedia-search\"></span>
    + <button class="cdx-button cdx-button--weight-quiet cdx-button--icon-only vector-sticky-header-search-toggle" data-event-name="ui.vector-sticky-search-form.icon" tabindex="-1"><span class="vector-icon mw-ui-icon-search mw-ui-icon-wikimedia-search"></span>

      <span>search</span>
      </button>
      		</div>
    - <div> </div>		<div class=\"vector-sticky-header-context-bar\">
    + <div> </div>		<div class="vector-sticky-header-context-bar">
    - 			<nav aria-label=\"\" class=\"vector-toc-landmark\">
    + 			<nav aria-label="" class="vector-toc-landmark">
    - <div id=\"vector-sticky-header-toc\" class=\"vector-dropdown mw-portlet mw-portlet-sticky-header-toc vector-sticky-header-toc\">
    + <div id="vector-sticky-header-toc" class="vector-dropdown mw-portlet mw-portlet-sticky-header-toc vector-sticky-header-toc">
    - 	<input type=\"checkbox\" id=\"vector-sticky-header-toc-checkbox\" role=\"button\" aria-haspopup=\"true\" data-event-name=\"ui.dropdown-vector-sticky-header-toc\" class=\"vector-dropdown-checkbox\" aria-label=\"\" tabindex=\"-1\">
    + 	<input type="checkbox" id="vector-sticky-header-toc-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-sticky-header-toc" class="vector-dropdown-checkbox" aria-label="" tabindex="-1">
    - 	<label id=\"vector-sticky-header-toc-label\" for=\"vector-sticky-header-toc-checkbox\" class=\"vector-dropdown-label cdx-button cdx-button--weight-quiet cdx-button--icon-only\" aria-hidden=\"true\" tabindex=\"-1\"><span class=\"vector-dropdown-label-text\"></span>
    + 	<label id="vector-sticky-header-toc-label" for="vector-sticky-header-toc-checkbox" class="vector-dropdown-label cdx-button cdx-button--weight-quiet cdx-button--icon-only" aria-hidden="true" tabindex="-1"><span class="vector-dropdown-label-text"></span>
      	</label>
    - 	<div class=\"vector-dropdown-content\">
    + 	<div class="vector-dropdown-content">

      	</div>
      </div>
      			</nav>
    - 			<div class=\"vector-sticky-header-context-bar-primary\" aria-hidden=\"true\"></div>
    + 			<div class="vector-sticky-header-context-bar-primary" aria-hidden="true"></div>
      		</div>
      	</div>
    - 	<div class=\"vector-sticky-header-end\" aria-hidden=\"true\">
    + 	<div class="vector-sticky-header-end" aria-hidden="true">
    - 		<div class=\"vector-sticky-header-icons\">
    + 		<div class="vector-sticky-header-icons">
    - <a href=\"#\" class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon\" id=\"ca-talk-sticky-header\" data-event-name=\"talk-sticky-header\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-speechBubbles mw-ui-icon-wikimedia-speechBubbles\"></span>
    + <a href="#" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon" id="ca-talk-sticky-header" data-event-name="talk-sticky-header" tabindex="-1"><span class="vector-icon mw-ui-icon-speechBubbles mw-ui-icon-wikimedia-speechBubbles"></span>

      <span></span>
      </a>
    - <a href=\"#\" class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon\" id=\"ca-history-sticky-header\" data-event-name=\"history-sticky-header\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-history mw-ui-icon-wikimedia-history\"></span>
    + <a href="#" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon" id="ca-history-sticky-header" data-event-name="history-sticky-header" tabindex="-1"><span class="vector-icon mw-ui-icon-history mw-ui-icon-wikimedia-history"></span>

      <span></span>
      </a>
    - <a href=\"#\" class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon mw-watchlink\" id=\"ca-watchstar-sticky-header\" data-event-name=\"watch-sticky-header\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-star mw-ui-icon-wikimedia-star\"></span>
    + <a href="#" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon mw-watchlink" id="ca-watchstar-sticky-header" data-event-name="watch-sticky-header" tabindex="-1"><span class="vector-icon mw-ui-icon-star mw-ui-icon-wikimedia-star"></span>

      <span></span>
      </a>
    - <a href=\"#\" class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon\" id=\"ca-ve-edit-sticky-header\" data-event-name=\"ve-edit-sticky-header\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-edit mw-ui-icon-wikimedia-edit\"></span>
    + <a href="#" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon" id="ca-ve-edit-sticky-header" data-event-name="ve-edit-sticky-header" tabindex="-1"><span class="vector-icon mw-ui-icon-edit mw-ui-icon-wikimedia-edit"></span>

      <span></span>
      </a>
    - <a href=\"#\" class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon\" id=\"ca-edit-sticky-header\" data-event-name=\"wikitext-edit-sticky-header\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-wikiText mw-ui-icon-wikimedia-wikiText\"></span>
    + <a href="#" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon" id="ca-edit-sticky-header" data-event-name="wikitext-edit-sticky-header" tabindex="-1"><span class="vector-icon mw-ui-icon-wikiText mw-ui-icon-wikimedia-wikiText"></span>

      <span></span>
      </a>
    - <a href=\"#\" class=\"cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon\" id=\"ca-viewsource-sticky-header\" data-event-name=\"editLock\" tabindex=\"-1\"><span class=\"vector-icon mw-ui-icon-star mw-ui-icon-wikimedia-star\"></span>
    + <a href="#" class="cdx-button cdx-button--weight-quiet cdx-button--icon-only sticky-header-icon" id="ca-viewsource-sticky-header" data-event-name="editLock" tabindex="-1"><span class="vector-icon mw-ui-icon-star mw-ui-icon-wikimedia-star"></span>

      <span></span>
      </a>
      		</div>
    - 		<div class=\"vector-sticky-header-buttons\">
    + 		<div class="vector-sticky-header-buttons">
    - <button class=\"cdx-button cdx-button--weight-quiet mw-interlanguage-selector\" id=\"p-lang-btn-sticky-header\" data-event-name=\"ui.dropdown-p-lang-btn-sticky-header\" tabindex=\"-1\"><span>0 languages</span>
    + <button class="cdx-button cdx-button--weight-quiet mw-interlanguage-selector" id="p-lang-btn-sticky-header" data-event-name="ui.dropdown-p-lang-btn-sticky-header" tabindex="-1"><span>0 languages</span>
      </button>
      		</div>
    - 		<div class=\"vector-sticky-header-icon-end\">
    + 		<div class="vector-sticky-header-icon-end">
    - 			<div class=\"vector-user-links\">
    + 			<div class="vector-user-links">
      			</div>
      		</div>
      	</div>
      </div>
      "

      135 |
      136 | test( 'Sticky header renders', () => {
    > 137 | 	expect( document.body.innerHTML ).toMatchSnapshot();
          | 	                                  ^
      138 | } );
      139 |
      140 | describe( 'sticky header', () => {

      at Object.<anonymous> (tests/jest/stickyHeader.test.js:137:36)

 › 1 snapshot failed.
PASS tests/jest/popupNotification.test.js
PASS tests/jest/skins.vector.js/portlets.test.js
FAIL tests/jest/skins.vector.js/menuTabs.test.js
  ● menuTabs › adds vector-tab-noicon class to li element when part of tabs

    expect(received).toMatchSnapshot()

    Snapshot name: `menuTabs adds vector-tab-noicon class to li element when part of tabs 1`

    - Snapshot  - 5
    + Received  + 5

    @@ -1,11 +1,11 @@
      "
    - 				<div id=\"p-views\" class=\"vector-menu mw-portlet mw-portlet-views vector-menu-tabs\">
    + 				<div id="p-views" class="vector-menu mw-portlet mw-portlet-views vector-menu-tabs">
    - 					<div class=\"vector-menu-content\">
    + 					<div class="vector-menu-content">
    - 						<ul class=\"vector-menu-content-list\">
    + 						<ul class="vector-menu-content-list">
    - 							<li class=\"mw-list-item mw-list-item-js vector-tab-noicon\" id=\"test-id\">
    + 							<li class="mw-list-item mw-list-item-js vector-tab-noicon" id="test-id">
    - 								<a href=\"#test-href\">
    + 								<a href="#test-href">
      									<span>
      										test link content
      									</span>
      								</a>
      							</li>

      44 | 		mw.hook( 'util' ).fire( menuItem, { id: 'test-id' } );
      45 |
    > 46 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      47 | 	} );
      48 |
      49 | 	test( 'does not add vector-tab-noicon class to li element when not part of tabs', () => {

      at Object.<anonymous> (tests/jest/skins.vector.js/menuTabs.test.js:46:37)

  ● menuTabs › does not add vector-tab-noicon class to li element when not part of tabs

    expect(received).toMatchSnapshot()

    Snapshot name: `menuTabs does not add vector-tab-noicon class to li element when not part of tabs 1`

    - Snapshot  - 5
    + Received  + 5

    @@ -1,11 +1,11 @@
      "
    - 			<div id=\"p-variants\" class=\"vector-menu mw-portlet mw-portlet-variants\">
    + 			<div id="p-variants" class="vector-menu mw-portlet mw-portlet-variants">
    - 				<div class=\"vector-menu-content\">
    + 				<div class="vector-menu-content">
    - 					<ul class=\"vector-menu-content-list\">
    + 					<ul class="vector-menu-content-list">
    - 						<li class=\"mw-list-item mw-list-item-js\" id=\"test-id\">
    + 						<li class="mw-list-item mw-list-item-js" id="test-id">
    - 							<a href=\"#test-href\">
    + 							<a href="#test-href">
      								<span>
      									test link content
      								</span>
      							</a>
      						</li>

      67 | 		mw.hook( 'util' ).fire( menuItem, { id: 'test-id' } );
      68 |
    > 69 | 		expect( document.body.innerHTML ).toMatchSnapshot();
         | 		                                  ^
      70 | 	} );
      71 | } );
      72 |

      at Object.<anonymous> (tests/jest/skins.vector.js/menuTabs.test.js:69:37)

 › 2 snapshots failed.
PASS tests/jest/skins.vector.es6/features.test.js
FAIL tests/jest/skins.vector.clientPreferences.test.js
  ● clientPreferences › render font size

    expect(received).toMatchSnapshot()

    Snapshot name: `clientPreferences render font size 1`

    - Snapshot  - 5
    + Received  + 5

      "<div>
    - 			<div class=\"vector-menu-heading\">Width</div>
    + 			<div class="vector-menu-heading">Width</div>
    - 			<div class=\"vector-menu-content\">
    + 			<div class="vector-menu-content">
    - 				<ul class=\"vector-menu-content-list\"></ul>
    + 				<ul class="vector-menu-content-list"></ul>
    - 			<span class=\"skin-client-pref-exclusion-notice\">msg:vector-feature-custom-font-size-exclusion-notice</span></div>
    + 			<span class="skin-client-pref-exclusion-notice">msg:vector-feature-custom-font-size-exclusion-notice</span></div>
    - 		<li><div class=\"\"><form><div class=\"cdx-radio\"><input name=\"skin-client-pref-vector-feature-custom-font-size-group\" id=\"skin-client-pref-vector-feature-custom-font-size-value-0\" type=\"radio\" value=\"0\" data-event-name=\"skin-client-pref-vector-feature-custom-font-size-value-0\" class=\"cdx-radio__input\"><span class=\"cdx-radio__icon\"></span><label class=\"cdx-label cdx-radio__label\" for=\"skin-client-pref-vector-feature-custom-font-size-value-0\"><span class=\"cdx-label__label__text\">vector-feature-custom-font-size-0-label</span></label></div><div class=\"cdx-radio\"><input name=\"skin-client-pref-vector-feature-custom-font-size-group\" id=\"skin-client-pref-vector-feature-custom-font-size-value-1\" type=\"radio\" value=\"1\" data-event-name=\"skin-client-pref-vector-feature-custom-font-size-value-1\" class=\"cdx-radio__input\"><span class=\"cdx-radio__icon\"></span><label class=\"cdx-label cdx-radio__label\" for=\"skin-client-pref-vector-feature-custom-font-size-value-1\"><span class=\"cdx-label__label__text\">vector-feature-custom-font-size-1-label</span></label></div><div class=\"cdx-radio\"><input name=\"skin-client-pref-vector-feature-custom-font-size-group\" id=\"skin-client-pref-vector-feature-custom-font-size-value-2\" type=\"radio\" value=\"2\" data-event-name=\"skin-client-pref-vector-feature-custom-font-size-value-2\" class=\"cdx-radio__input\"><span class=\"cdx-radio__icon\"></span><label class=\"cdx-label cdx-radio__label\" for=\"skin-client-pref-vector-feature-custom-font-size-value-2\"><span class=\"cdx-label__label__text\">vector-feature-custom-font-size-2-label</span></label></div></form></div></li></div>"
    + 		<li><div class=""><form><div class="cdx-radio"><input name="skin-client-pref-vector-feature-custom-font-size-group" id="skin-client-pref-vector-feature-custom-font-size-value-0" type="radio" value="0" data-event-name="skin-client-pref-vector-feature-custom-font-size-value-0" class="cdx-radio__input"><span class="cdx-radio__icon"></span><label class="cdx-label cdx-radio__label" for="skin-client-pref-vector-feature-custom-font-size-value-0"><span class="cdx-label__label__text">vector-feature-custom-font-size-0-label</span></label></div><div class="cdx-radio"><input name="skin-client-pref-vector-feature-custom-font-size-group" id="skin-client-pref-vector-feature-custom-font-size-value-1" type="radio" value="1" data-event-name="skin-client-pref-vector-feature-custom-font-size-value-1" class="cdx-radio__input"><span class="cdx-radio__icon"></span><label class="cdx-label cdx-radio__label" for="skin-client-pref-vector-feature-custom-font-size-value-1"><span class="cdx-label__label__text">vector-feature-custom-font-size-1-label</span></label></div><div class="cdx-radio"><input name="skin-client-pref-vector-feature-custom-font-size-group" id="skin-client-pref-vector-feature-custom-font-size-value-2" type="radio" value="2" data-event-name="skin-client-pref-vector-feature-custom-font-size-value-2" class="cdx-radio__input"><span class="cdx-radio__icon"></span><label class="cdx-label cdx-radio__label" for="skin-client-pref-vector-feature-custom-font-size-value-2"><span class="cdx-label__label__text">vector-feature-custom-font-size-2-label</span></label></div></form></div></li></div>"

      46 | 			}
      47 | 		} ).then( () => {
    > 48 | 			expect( cp.innerHTML ).toMatchSnapshot();
         | 			                       ^
      49 | 		} );
      50 | 	} );
      51 |

      at tests/jest/skins.vector.clientPreferences.test.js:48:27

  ● clientPreferences › doesnt render exclusion notice if the msg key doesnt exist

    expect(received).toMatchSnapshot()

    Snapshot name: `clientPreferences doesnt render exclusion notice if the msg key doesnt exist 1`

    - Snapshot  - 4
    + Received  + 4

      "<div>
    - 			<div class=\"vector-menu-heading\">Width</div>
    + 			<div class="vector-menu-heading">Width</div>
    - 			<div class=\"vector-menu-content\">
    + 			<div class="vector-menu-content">
    - 				<ul class=\"vector-menu-content-list\"></ul>
    + 				<ul class="vector-menu-content-list"></ul>
      			</div>
    - 		<li><div class=\"\"><form><div class=\"cdx-radio\"><input name=\"skin-client-pref-vector-feature-limited-width-group\" id=\"skin-client-pref-vector-feature-limited-width-value-1\" type=\"radio\" value=\"1\" data-event-name=\"skin-client-pref-vector-feature-limited-width-value-1\" class=\"cdx-radio__input\"><span class=\"cdx-radio__icon\"></span><label class=\"cdx-label cdx-radio__label\" for=\"skin-client-pref-vector-feature-limited-width-value-1\"><span class=\"cdx-label__label__text\">vector-feature-limited-width-1-label</span></label></div><div class=\"cdx-radio\"><input name=\"skin-client-pref-vector-feature-limited-width-group\" id=\"skin-client-pref-vector-feature-limited-width-value-0\" type=\"radio\" value=\"0\" data-event-name=\"skin-client-pref-vector-feature-limited-width-value-0\" class=\"cdx-radio__input\"><span class=\"cdx-radio__icon\"></span><label class=\"cdx-label cdx-radio__label\" for=\"skin-client-pref-vector-feature-limited-width-value-0\"><span class=\"cdx-label__label__text\">vector-feature-limited-width-0-label</span></label></div></form></div></li></div>"
    + 		<li><div class=""><form><div class="cdx-radio"><input name="skin-client-pref-vector-feature-limited-width-group" id="skin-client-pref-vector-feature-limited-width-value-1" type="radio" value="1" data-event-name="skin-client-pref-vector-feature-limited-width-value-1" class="cdx-radio__input"><span class="cdx-radio__icon"></span><label class="cdx-label cdx-radio__label" for="skin-client-pref-vector-feature-limited-width-value-1"><span class="cdx-label__label__text">vector-feature-limited-width-1-label</span></label></div><div class="cdx-radio"><input name="skin-client-pref-vector-feature-limited-width-group" id="skin-client-pref-vector-feature-limited-width-value-0" type="radio" value="0" data-event-name="skin-client-pref-vector-feature-limited-width-value-0" class="cdx-radio__input"><span class="cdx-radio__icon"></span><label class="cdx-label cdx-radio__label" for="skin-client-pref-vector-feature-limited-width-value-0"><span class="cdx-label__label__text">vector-feature-limited-width-0-label</span></label></div></form></div></li></div>"

      63 | 			}
      64 | 		} ).then( () => {
    > 65 | 			expect( cp.innerHTML ).toMatchSnapshot();
         | 			                       ^
      66 | 		} );
      67 | 	} );
      68 |

      at tests/jest/skins.vector.clientPreferences.test.js:65:27

  ● clientPreferences › render toggle

    expect(received).toMatchSnapshot()

    Snapshot name: `clientPreferences render toggle 1`

    - Snapshot  - 5
    + Received  + 5

      "<div>
    - 			<div class=\"vector-menu-heading\">Width</div>
    + 			<div class="vector-menu-heading">Width</div>
    - 			<div class=\"vector-menu-content\">
    + 			<div class="vector-menu-content">
    - 				<ul class=\"vector-menu-content-list\"></ul>
    + 				<ul class="vector-menu-content-list"></ul>
    - 			<span class=\"skin-client-pref-exclusion-notice\">msg:expandAll-exclusion-notice</span></div>
    + 			<span class="skin-client-pref-exclusion-notice">msg:expandAll-exclusion-notice</span></div>
    - 		<li><div class=\"\"><form><span class=\"cdx-toggle-switch\"><input name=\"skin-client-pref-expandAll-group\" id=\"skin-client-pref-expandAll-value-1\" type=\"checkbox\" data-event-name=\"skin-client-pref-expandAll-value-1\" class=\"cdx-toggle-switch__input\"><span class=\"cdx-toggle-switch__switch\"><span class=\"cdx-toggle-switch__switch__grip\"></span></span><label class=\"cdx-toggle-switch__label\">msg:expandAll-name</label></span></form></div></li></div>"
    + 		<li><div class=""><form><span class="cdx-toggle-switch"><input name="skin-client-pref-expandAll-group" id="skin-client-pref-expandAll-value-1" type="checkbox" data-event-name="skin-client-pref-expandAll-value-1" class="cdx-toggle-switch__input"><span class="cdx-toggle-switch__switch"><span class="cdx-toggle-switch__switch__grip"></span></span><label class="cdx-toggle-switch__label">msg:expandAll-name</label></span></form></div></li></div>"

      76 | 			}
      77 | 		} ).then( () => {
    > 78 | 			expect( cp.innerHTML ).toMatchSnapshot();
         | 			                       ^
      79 | 		} );
      80 | 	} );
      81 | } );

      at tests/jest/skins.vector.clientPreferences.test.js:78:27

 › 3 snapshots failed.
PASS tests/jest/deferUntilFrame.test.js
FAIL tests/jest/userLinks.test.js
  ● UserLinks renders

    expect(received).toMatchSnapshot()

    Snapshot name: `UserLinks renders 1`

    - Snapshot  - 41
    + Received  + 41

    @@ -1,83 +1,83 @@
    - "<nav class=\"vector-user-links\" aria-label=\"\">
    + "<nav class="vector-user-links" aria-label="">
    - 	<div class=\"vector-user-links-main\">
    + 	<div class="vector-user-links-main">
    - <div id=\"p-personal-preferences\" class=\"vector-menu\">
    + <div id="p-personal-preferences" class="vector-menu">
    - <div class=\"vector-menu-content\">
    + <div class="vector-menu-content">
      	
    - 	<ul class=\"vector-menu-content-list\">
    + 	<ul class="vector-menu-content-list">
    - 		<li id=\"ca-uls\" class=\"user-links-collapsible-item mw-list-item active\"><a href=\"#\" class=\"uls-trigger cdx-button cdx-button--weight-quiet\"><span class=\"vector-icon mw-ui-icon-wikimedia-language\"></span> <span>English</span></a></li>
    + 		<li id="ca-uls" class="user-links-collapsible-item mw-list-item active"><a href="#" class="uls-trigger cdx-button cdx-button--weight-quiet"><span class="vector-icon mw-ui-icon-wikimedia-language"></span> <span>English</span></a></li>
      	</ul>
      	
      </div>
      </div>
    - <div id=\"p-personal-user-page\" class=\"vector-menu\">
    + <div id="p-personal-user-page" class="vector-menu">
    - <div class=\"vector-menu-content\">
    + <div class="vector-menu-content">
      	
    - 	<ul class=\"vector-menu-content-list\">
    + 	<ul class="vector-menu-content-list">
    - 		<li id=\"pt-userpage-2\" class=\"user-links-collapsible-item mw-list-item\"><a href=\"/wiki/User:Admin\" class=\"cdx-button cdx-button--weight-quiet\" title=\"Your user page [⌃⌥.]\" accesskey=\".\"><span>Admin</span></a></li>
    + 		<li id="pt-userpage-2" class="user-links-collapsible-item mw-list-item"><a href="/wiki/User:Admin" class="cdx-button cdx-button--weight-quiet" title="Your user page [⌃⌥.]" accesskey="."><span>Admin</span></a></li>
      	</ul>
      	
      </div>
      </div>
    - 	<nav class=\"vector-appearance-landmark\" aria-label=\"\">
    + 	<nav class="vector-appearance-landmark" aria-label="">
      	</nav>
    - <div id=\"p-personal-notifications\" class=\"vector-menu\">
    + <div id="p-personal-notifications" class="vector-menu">
    - <div class=\"vector-menu-content\">
    + <div class="vector-menu-content">
      	
    - 	<ul class=\"vector-menu-content-list\">
    + 	<ul class="vector-menu-content-list">
    - 		<li id=\"pt-notifications-alert\" class=\"mw-list-item\"><a href=\"/wiki/Special:Notifications\" class=\"mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-bell mw-echo-notifications-badge-all-read\" data-counter-num=\"0\" data-counter-text=\"0\" title=\"Your alerts\"><span>Alerts (0)</span></a></li>
    + 		<li id="pt-notifications-alert" class="mw-list-item"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-bell mw-echo-notifications-badge-all-read" data-counter-num="0" data-counter-text="0" title="Your alerts"><span>Alerts (0)</span></a></li>
    - 		<li id=\"pt-notifications-notice\" class=\"mw-list-item\"><a href=\"/wiki/Special:Notifications\" class=\"mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-tray mw-echo-notifications-badge-all-read\" data-counter-num=\"0\" data-counter-text=\"0\" title=\"Your notices\"><span>Notices (0)</span></a></li>
    + 		<li id="pt-notifications-notice" class="mw-list-item"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-tray mw-echo-notifications-badge-all-read" data-counter-num="0" data-counter-text="0" title="Your notices"><span>Notices (0)</span></a></li>
      	</ul>
      	
      </div>
      </div>
    - <div id=\"p-personal-more\" class=\"vector-menu mw-portlet mw-portlet-vector-user-menu-overflow vector-user-menu-overflow\">
    + <div id="p-personal-more" class="vector-menu mw-portlet mw-portlet-vector-user-menu-overflow vector-user-menu-overflow">
    - 	<div class=\"vector-menu-heading\">
    + 	<div class="vector-menu-heading">
      		Toggle sidebar
      	</div>
    - <div class=\"vector-menu-content\">
    + <div class="vector-menu-content">
      	
    - 	<ul class=\"vector-menu-content-list\">
    + 	<ul class="vector-menu-content-list">
      		
    - 			<li id=\"pt-watchlist-2\" class=\"user-links-collapsible-item mw-list-item\"><a href=\"/wiki/Special:Watchlist\" class=\"cdx-button cdx-button--weight-quiet vector-icon cdx-button--icon-only mw-ui-icon-watchlist mw-ui-icon-wikimedia-watchlist\" title=\"A list of pages you are monitoring for changes [⌃⌥l]\" accesskey=\"l\"><span>Watchlist</span></a></li>
    + 			<li id="pt-watchlist-2" class="user-links-collapsible-item mw-list-item"><a href="/wiki/Special:Watchlist" class="cdx-button cdx-button--weight-quiet vector-icon cdx-button--icon-only mw-ui-icon-watchlist mw-ui-icon-wikimedia-watchlist" title="A list of pages you are monitoring for changes [⌃⌥l]" accesskey="l"><span>Watchlist</span></a></li>
      		
      	</ul>
      	
      </div>
      </div>
      	</div>
    - <div id=\"vector-user-links-dropdown\" class=\"vector-dropdown vector-user-menu vector-user-menu-logged-in\">
    + <div id="vector-user-links-dropdown" class="vector-dropdown vector-user-menu vector-user-menu-logged-in">
    - 	<input type=\"checkbox\" id=\"vector-user-links-dropdown-checkbox\" role=\"button\" aria-haspopup=\"true\" data-event-name=\"ui.dropdown-vector-user-links-dropdown\" class=\"vector-dropdown-checkbox\" aria-label=\"Personal tools\">
    + 	<input type="checkbox" id="vector-user-links-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-user-links-dropdown" class="vector-dropdown-checkbox" aria-label="Personal tools">
    - 	<label id=\"vector-user-links-dropdown-label\" for=\"vector-user-links-dropdown-checkbox\" class=\"vector-dropdown-label\" aria-hidden=\"true\"><span class=\"vector-dropdown-label-text\">Personal tools</span>
    + 	<label id="vector-user-links-dropdown-label" for="vector-user-links-dropdown-checkbox" class="vector-dropdown-label" aria-hidden="true"><span class="vector-dropdown-label-text">Personal tools</span>
      	</label>
    - 	<div class=\"vector-dropdown-content\">
    + 	<div class="vector-dropdown-content">

    - <div id=\"p-personal\" class=\"vector-menu mw-portlet mw-portlet-personal\">
    + <div id="p-personal" class="vector-menu mw-portlet mw-portlet-personal">
    - <div class=\"vector-menu-content\">
    + <div class="vector-menu-content">
      	
    - 	<ul class=\"vector-menu-content-list\">
    + 	<ul class="vector-menu-content-list">
      		
    - 			<li id=\"pt-userpage\" class=\"user-links-collapsible-item mw-list-item\"><a href=\"/wiki/User:Admin\" title=\"Your user page [.]\" accesskey=\".\"><span class=\"vector-icon mw-ui-icon-userAvatar mw-ui-icon-wikimedia-userAvatar\"></span> <span>Admin</span></a></li>
    + 			<li id="pt-userpage" class="user-links-collapsible-item mw-list-item"><a href="/wiki/User:Admin" title="Your user page [.]" accesskey="."><span class="vector-icon mw-ui-icon-userAvatar mw-ui-icon-wikimedia-userAvatar"></span> <span>Admin</span></a></li>
    - 			<li id=\"pt-mytalk\" class=\"mw-list-item\"><a href=\"/wiki/User_talk:Admin\" title=\"Your talk page [n]\" accesskey=\"n\"><span class=\"vector-icon mw-ui-icon-userTalk mw-ui-icon-wikimedia-userTalk\"></span> <span>Talk</span></a></li>
    + 			<li id="pt-mytalk" class="mw-list-item"><a href="/wiki/User_talk:Admin" title="Your talk page [n]" accesskey="n"><span class="vector-icon mw-ui-icon-userTalk mw-ui-icon-wikimedia-userTalk"></span> <span>Talk</span></a></li>
    - 			<li id=\"pt-sandbox\" class=\"new mw-list-item\"><a href=\"/w/index.php?title=User:Admin/sandbox&amp;action=edit&amp;redlink=1\" title=\"Your sandbox (page does not exist)\"><span class=\"vector-icon mw-ui-icon-sandbox mw-ui-icon-wikimedia-sandbox\"></span> <span>Sandbox</span></a></li>
    + 			<li id="pt-sandbox" class="new mw-list-item"><a href="/w/index.php?title=User:Admin/sandbox&amp;action=edit&amp;redlink=1" title="Your sandbox (page does not exist)"><span class="vector-icon mw-ui-icon-sandbox mw-ui-icon-wikimedia-sandbox"></span> <span>Sandbox</span></a></li>
    - 			<li id=\"pt-preferences\" class=\"mw-list-item\"><a href=\"/wiki/Special:Preferences\" title=\"Your preferences\"><span class=\"vector-icon mw-ui-icon-appearance mw-ui-icon-wikimedia-appearance\"></span> <span>Preferences</span></a></li>
    + 			<li id="pt-preferences" class="mw-list-item"><a href="/wiki/Special:Preferences" title="Your preferences"><span class="vector-icon mw-ui-icon-appearance mw-ui-icon-wikimedia-appearance"></span> <span>Preferences</span></a></li>
    - 			<li id=\"pt-betafeatures\" class=\"mw-list-item\"><a href=\"/wiki/Special:Preferences#mw-prefsection-betafeatures\" title=\"Beta features\"><span class=\"vector-icon mw-ui-icon-labFlask mw-ui-icon-wikimedia-labFlask\"></span> <span>Beta</span></a></li>
    + 			<li id="pt-betafeatures" class="mw-list-item"><a href="/wiki/Special:Preferences#mw-prefsection-betafeatures" title="Beta features"><span class="vector-icon mw-ui-icon-labFlask mw-ui-icon-wikimedia-labFlask"></span> <span>Beta</span></a></li>
    - 			<li id=\"pt-watchlist\" class=\"user-links-collapsible-item mw-list-item\"><a href=\"/wiki/Special:Watchlist\" title=\"A list of pages you are monitoring for changes [l]\" accesskey=\"l\"><span class=\"vector-icon mw-ui-icon-watchlist mw-ui-icon-wikimedia-watchlist\"></span> <span>Watchlist</span></a></li>
    + 			<li id="pt-watchlist" class="user-links-collapsible-item mw-list-item"><a href="/wiki/Special:Watchlist" title="A list of pages you are monitoring for changes [l]" accesskey="l"><span class="vector-icon mw-ui-icon-watchlist mw-ui-icon-wikimedia-watchlist"></span> <span>Watchlist</span></a></li>
    - 			<li id=\"pt-uploads\" class=\"mw-list-item\"><a href=\"/w/index.php?title=Special:ListFiles/Admin&amp;ilshowall=1\" title=\"List of files you have uploaded\"><span class=\"vector-icon mw-ui-icon-imageGallery mw-ui-icon-wikimedia-imageGallery\"></span> <span>Uploads</span></a></li>
    + 			<li id="pt-uploads" class="mw-list-item"><a href="/w/index.php?title=Special:ListFiles/Admin&amp;ilshowall=1" title="List of files you have uploaded"><span class="vector-icon mw-ui-icon-imageGallery mw-ui-icon-wikimedia-imageGallery"></span> <span>Uploads</span></a></li>
    - 			<li id=\"pt-mycontris\" class=\"mw-list-item\"><a href=\"/wiki/Special:Contributions/Admin\" title=\"A list of your contributions [y]\" accesskey=\"y\"><span class=\"vector-icon mw-ui-icon-userContributions mw-ui-icon-wikimedia-userContributions\"></span> <span>Contributions</span></a></li>
    + 			<li id="pt-mycontris" class="mw-list-item"><a href="/wiki/Special:Contributions/Admin" title="A list of your contributions [y]" accesskey="y"><span class="vector-icon mw-ui-icon-userContributions mw-ui-icon-wikimedia-userContributions"></span> <span>Contributions</span></a></li>
    - 			<li id=\"pt-custom\" class=\"mw-list-item mw-list-item-js\">Gadget added item</li>
    + 			<li id="pt-custom" class="mw-list-item mw-list-item-js">Gadget added item</li>
      		
      	</ul>
      	
      </div>
      </div>
    - <div id=\"p-user-menu-logout\" class=\"vector-menu mw-portlet mw-portlet-user-menu-logout\">
    + <div id="p-user-menu-logout" class="vector-menu mw-portlet mw-portlet-user-menu-logout">
    - <div class=\"vector-menu-content\">
    + <div class="vector-menu-content">
      	
    - 	<ul class=\"vector-menu-content-list\">
    + 	<ul class="vector-menu-content-list">
      		
    - 			<li id=\"ca-logout\" class=\"mw-list-item\"><a data-mw-interface=\"1\" href=\"/w/index.php?title=Special:UserLogout&amp;returnto=Main+Page\" title=\"Log out\"><span class=\"vector-icon mw-ui-icon-logOut mw-ui-icon-wikimedia-logOut\"></span> <span>Log out</span></a></li>
    + 			<li id="ca-logout" class="mw-list-item"><a data-mw-interface="1" href="/w/index.php?title=Special:UserLogout&amp;returnto=Main+Page" title="Log out"><span class="vector-icon mw-ui-icon-logOut mw-ui-icon-wikimedia-logOut"></span> <span>Log out</span></a></li>
      		
      	</ul>
      	
      </div>
      </div>

       6 |
       7 | test( 'UserLinks renders', () => {
    >  8 | 	expect( document.body.innerHTML ).toMatchSnapshot();
         | 	                                  ^
       9 | } );
      10 |

      at Object.<anonymous> (tests/jest/userLinks.test.js:8:36)

 › 1 snapshot failed.
Jest: "global" coverage threshold for statements (48%) not met: 33.6%
Jest: "global" coverage threshold for branches (35%) not met: 25.93%
Jest: "global" coverage threshold for lines (47%) not met: 33.65%
Jest: "global" coverage threshold for functions (45%) not met: 27.81%
Snapshot Summary
 › 17 snapshots failed from 7 test suites. Inspect your code changes or run `npm run test:unit -- -u` to update them.

Test Suites: 9 failed, 7 passed, 16 total
Tests:       17 failed, 42 passed, 59 total
Snapshots:   17 failed, 1 passed, 18 total
Time:        5.278 s
--- stdout ---

> test
> npm -s run lint && tsc && npm run test:unit


/src/repo/resources/skins.vector.js/tableOfContents.js
  76:1  warning  Syntax error in namepath: is-parent-section     jsdoc/valid-types
  77:1  warning  Syntax error in namepath: is-top-level-section  jsdoc/valid-types

✖ 2 problems (0 errors, 2 warnings)

Checked 1 message directory.

> test:unit
> jest --silent

--------------------------------|---------|----------|---------|---------|-------------------------------------------------------------------------------------------
File                            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                                         
--------------------------------|---------|----------|---------|---------|-------------------------------------------------------------------------------------------
All files                       |    33.6 |    25.93 |   27.81 |   33.65 |                                                                                           
 skins.vector.clientPreferences |   57.67 |    35.63 |   57.14 |   57.34 |                                                                                           
  clientPreferences.js          |   57.67 |    35.63 |   57.14 |   57.34 | 67-98,158-177,196,210,217-275,304,341,347,368,373-374,391,398-401,416,446-449,467,487-506 
 skins.vector.js                |   31.55 |    27.11 |   26.39 |   31.77 |                                                                                           
  deferUntilFrame.js            |     100 |      100 |     100 |     100 |                                                                                           
  disableNightModeIfGadget.js   |      70 |       70 |      60 |      70 | 59-77,90                                                                                  
  dropdownMenus.js              |   90.38 |       80 |   83.33 |   90.38 | 26,89,99,132,161                                                                          
  features.js                   |   71.42 |    57.89 |      50 |   71.42 | 19-20,26-27,87-105                                                                        
  languageButton.js             |       0 |        0 |       0 |       0 | 9-52                                                                                      
  menuTabs.js                   |     100 |      100 |     100 |     100 |                                                                                           
  pinnableElement.js            |   78.94 |    76.31 |      75 |   79.78 | 25,29-30,34-35,82-86,134,184,208,231,278-294                                              
  popupNotification.js          |   91.66 |    64.28 |      75 |   91.66 | 74,77                                                                                     
  portlets.js                   |   84.41 |    58.06 |      60 |   84.41 | 20,35-37,60,113,126-134                                                                   
  scrollObserver.js             |       0 |        0 |       0 |       0 | 2-52                                                                                      
  searchToggle.js               |   13.33 |        0 |       0 |   13.33 | 18-94,110-125                                                                             
  sectionObserver.js            |       0 |        0 |       0 |       0 | 46-191                                                                                    
  setupIntersectionObservers.js |       0 |        0 |       0 |       0 | 3-339                                                                                     
  skin.js                       |       0 |        0 |       0 |       0 | 1-153                                                                                     
  stickyHeader.js               |    15.9 |     2.96 |   19.44 |    15.9 | 27-80,107-124,141-153,182-401,439-441,461-600                                             
  stickyHeaderAB.js             |       0 |        0 |       0 |       0 |                                                                                           
  tableOfContents.js            |       0 |        0 |       0 |       0 | 6-633                                                                                     
  tables.js                     |   86.36 |    81.25 |     100 |   86.36 | 4,28,34                                                                                   
  userPreferences.js            |   33.33 |        0 |       0 |   33.33 | 8-10                                                                                      
  watchstar.js                  |      20 |        0 |       0 |      20 | 7-24,29-36                                                                                
 skins.vector.legacy.js         |   22.09 |    12.16 |    6.66 |   22.09 |                                                                                           
  collapsibleTabs.js            |       0 |        0 |       0 |       0 | 13-236                                                                                    
  portlets.js                   |   81.63 |    64.28 |   66.66 |   81.63 | 18,35-37,47,85-90                                                                         
  skin-legacy.js                |       0 |      100 |       0 |       0 | 4-19                                                                                      
  vector.js                     |       0 |        0 |       0 |       0 | 7-118                                                                                     
 skins.vector.search            |       0 |        0 |       0 |       0 |                                                                                           
  skins.vector.search.js        |       0 |        0 |       0 |       0 | 4-108                                                                                     
--------------------------------|---------|----------|---------|---------|-------------------------------------------------------------------------------------------

--- end ---
$ node_modules/.bin/jest -u
--- stderr ---
PASS tests/jest/stickyHeader.test.js
 › 1 snapshot updated.
PASS tests/jest/skins.vector.js/dropdownMenus.test.js
 › 2 snapshots updated.
PASS tests/jest/pinnableElement.test.js
 › 1 snapshot updated.
PASS tests/jest/skins.vector.js/menuTabs.test.js
 › 2 snapshots updated.
PASS tests/jest/skins.vector.clientPreferences.test.js
 › 3 snapshots updated.
PASS tests/jest/skins.vector.js/tables.test.js
 › 7 snapshots updated.
PASS tests/jest/userLinks.test.js
 › 1 snapshot updated.
PASS tests/jest/skins.vector.js/disableNightModeIfGadget.test.js
PASS tests/jest/features.test.js
PASS tests/jest/deferUntilFrame.test.js
PASS tests/jest/skins.vector.legacy.js/portlets.test.js
PASS tests/jest/popupNotification.test.js
PASS tests/jest/skins.vector.js/portlets.test.js
PASS tests/jest/skins.vector.es6/features.test.js
FAIL tests/jest/skins.vector.es6/main.test.js
  ● Test suite failed to run

    ● Invalid return value:
      `process()` or/and `processAsync()` method of code transformer found at 
      "/src/repo/node_modules/mustache-jest/index.js" 
      should return an object or a Promise resolving to an object. The object 
      must have `code` property with a string of processed code.
      This error may be caused by a breaking change in Jest 28:
      https://jestjs.io/docs/28.x/upgrading-to-jest28#transformer
      Code Transformation Documentation:
      https://jestjs.io/docs/code-transformation

      4 |  * TableOfContents Mustache templates
      5 |  */
    > 6 | const templateTocContents = require( /** @type {string} */ ( './templates/TableOfContents__list.mustache' ) );
        |                             ^
      7 | const templateTocLine = require( /** @type {string} */ ( './templates/TableOfContents__line.mustache' ) );
      8 | /**
      9 |  * TableOfContents Config object for filling mustache templates

      at ScriptTransformer._buildTransformResult (node_modules/@jest/transform/build/ScriptTransformer.js:442:15)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:554:17)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:674:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:726:19)
      at Object.require (resources/skins.vector.js/tableOfContents.js:6:29)
      at Object.require (resources/skins.vector.js/setupIntersectionObservers.js:6:24)
      at Object.<anonymous> (tests/jest/skins.vector.es6/main.test.js:8:18)

FAIL tests/jest/tableOfContents.test.js
  ● Test suite failed to run

    ● Invalid return value:
      `process()` or/and `processAsync()` method of code transformer found at 
      "/src/repo/node_modules/mustache-jest/index.js" 
      should return an object or a Promise resolving to an object. The object 
      must have `code` property with a string of processed code.
      This error may be caused by a breaking change in Jest 28:
      https://jestjs.io/docs/28.x/upgrading-to-jest28#transformer
      Code Transformation Documentation:
      https://jestjs.io/docs/code-transformation

      4 |  * TableOfContents Mustache templates
      5 |  */
    > 6 | const templateTocContents = require( /** @type {string} */ ( './templates/TableOfContents__list.mustache' ) );
        |                             ^
      7 | const templateTocLine = require( /** @type {string} */ ( './templates/TableOfContents__line.mustache' ) );
      8 | /**
      9 |  * TableOfContents Config object for filling mustache templates

      at ScriptTransformer._buildTransformResult (node_modules/@jest/transform/build/ScriptTransformer.js:442:15)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:554:17)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:674:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:726:19)
      at Object.require (resources/skins.vector.js/tableOfContents.js:6:29)
      at Object.<anonymous> (tests/jest/tableOfContents.test.js:9:29)

Jest: "global" coverage threshold for statements (48%) not met: 33.6%
Jest: "global" coverage threshold for branches (35%) not met: 25.93%
Jest: "global" coverage threshold for lines (47%) not met: 33.65%
Jest: "global" coverage threshold for functions (45%) not met: 27.81%
Snapshot Summary
 › 17 snapshots updated from 7 test suites.

Test Suites: 2 failed, 14 passed, 16 total
Tests:       59 passed, 59 total
Snapshots:   17 updated, 1 passed, 18 total
Time:        4.936 s
Ran all test suites.
--- stdout ---
--------------------------------|---------|----------|---------|---------|-------------------------------------------------------------------------------------------
File                            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                                         
--------------------------------|---------|----------|---------|---------|-------------------------------------------------------------------------------------------
All files                       |    33.6 |    25.93 |   27.81 |   33.65 |                                                                                           
 skins.vector.clientPreferences |   57.67 |    35.63 |   57.14 |   57.34 |                                                                                           
  clientPreferences.js          |   57.67 |    35.63 |   57.14 |   57.34 | 67-98,158-177,196,210,217-275,304,341,347,368,373-374,391,398-401,416,446-449,467,487-506 
 skins.vector.js                |   31.55 |    27.11 |   26.39 |   31.77 |                                                                                           
  deferUntilFrame.js            |     100 |      100 |     100 |     100 |                                                                                           
  disableNightModeIfGadget.js   |      70 |       70 |      60 |      70 | 59-77,90                                                                                  
  dropdownMenus.js              |   90.38 |       80 |   83.33 |   90.38 | 26,89,99,132,161                                                                          
  features.js                   |   71.42 |    57.89 |      50 |   71.42 | 19-20,26-27,87-105                                                                        
  languageButton.js             |       0 |        0 |       0 |       0 | 9-52                                                                                      
  menuTabs.js                   |     100 |      100 |     100 |     100 |                                                                                           
  pinnableElement.js            |   78.94 |    76.31 |      75 |   79.78 | 25,29-30,34-35,82-86,134,184,208,231,278-294                                              
  popupNotification.js          |   91.66 |    64.28 |      75 |   91.66 | 74,77                                                                                     
  portlets.js                   |   84.41 |    58.06 |      60 |   84.41 | 20,35-37,60,113,126-134                                                                   
  scrollObserver.js             |       0 |        0 |       0 |       0 | 2-52                                                                                      
  searchToggle.js               |   13.33 |        0 |       0 |   13.33 | 18-94,110-125                                                                             
  sectionObserver.js            |       0 |        0 |       0 |       0 | 46-191                                                                                    
  setupIntersectionObservers.js |       0 |        0 |       0 |       0 | 3-339                                                                                     
  skin.js                       |       0 |        0 |       0 |       0 | 1-153                                                                                     
  stickyHeader.js               |    15.9 |     2.96 |   19.44 |    15.9 | 27-80,107-124,141-153,182-401,439-441,461-600                                             
  stickyHeaderAB.js             |       0 |        0 |       0 |       0 |                                                                                           
  tableOfContents.js            |       0 |        0 |       0 |       0 | 6-633                                                                                     
  tables.js                     |   86.36 |    81.25 |     100 |   86.36 | 4,28,34                                                                                   
  userPreferences.js            |   33.33 |        0 |       0 |   33.33 | 8-10                                                                                      
  watchstar.js                  |      20 |        0 |       0 |      20 | 7-24,29-36                                                                                
 skins.vector.legacy.js         |   22.09 |    12.16 |    6.66 |   22.09 |                                                                                           
  collapsibleTabs.js            |       0 |        0 |       0 |       0 | 13-236                                                                                    
  portlets.js                   |   81.63 |    64.28 |   66.66 |   81.63 | 18,35-37,47,85-90                                                                         
  skin-legacy.js                |       0 |      100 |       0 |       0 | 4-19                                                                                      
  vector.js                     |       0 |        0 |       0 |       0 | 7-118                                                                                     
 skins.vector.search            |       0 |        0 |       0 |       0 |                                                                                           
  skins.vector.search.js        |       0 |        0 |       0 |       0 | 4-108                                                                                     
--------------------------------|---------|----------|---------|---------|-------------------------------------------------------------------------------------------

--- end ---
Traceback (most recent call last):
  File "/venv/lib/python3.13/site-packages/runner/__init__.py", line 289, in npm_test
    self.check_call(["npm", "test"])
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.13/site-packages/runner/shell2.py", line 66, in check_call
    res.check_returncode()
    ~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.13/subprocess.py", line 508, in check_returncode
    raise CalledProcessError(self.returncode, self.args, self.stdout,
                             self.stderr)
subprocess.CalledProcessError: Command '['/usr/bin/npm', 'test']' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/venv/lib/python3.13/site-packages/runner/__init__.py", line 1268, in main
    libup.run()
    ~~~~~~~~~^^
  File "/venv/lib/python3.13/site-packages/runner/__init__.py", line 1202, in run
    self.npm_upgrade(plan)
    ~~~~~~~~~~~~~~~~^^^^^^
  File "/venv/lib/python3.13/site-packages/runner/__init__.py", line 1064, in npm_upgrade
    self.npm_test()
    ~~~~~~~~~~~~~^^
  File "/venv/lib/python3.13/site-packages/runner/__init__.py", line 302, in npm_test
    self.check_call(["node_modules/.bin/jest", *jest_config, "-u"])
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.13/site-packages/runner/shell2.py", line 66, in check_call
    res.check_returncode()
    ~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.13/subprocess.py", line 508, in check_returncode
    raise CalledProcessError(self.returncode, self.args, self.stdout,
                             self.stderr)
subprocess.CalledProcessError: Command '['node_modules/.bin/jest', '-u']' returned non-zero exit status 1.
Source code is licensed under the AGPL.