String.prototype.replaceAll() — полезный метод, и при сборке и выполнении все работает нормально. Однако все Jest-тесты завершаются со следующей ошибкой:
TypeError: replaceAll is not a function
Это мои зависимости:
"dependencies": {
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
"vue-i18n": "^8.22.0",
"vue-property-decorator": "^8.4.2",
"vue-router": "^3.3.4",
"vuex": "^3.5.1"
},
"devDependencies": {
"@vue/test-utils": "^1.1.0",
"jest-junit": "^12.0.0",
"ts-jest": "^26.4.1",
"typescript": "~3.9.3",
"vue-jest": "^3.0.7",
"vue-template-compiler": "^2.6.10"
},
Как я могу исправить это поведение?
Скорее всего, это происходит потому, что String.prototype.replaceAll
не реализован в Node.js (по крайней мере, в версии v14.15.0
).
Одной из альтернатив, которые вы могли бы использовать, являются регулярные выражения, как в этом примере:
const str = 'foo-foo';
const regex = /foo/g; // Note the 'g' flag, which matches all occurrences of the expression
console.info(str.replace(regex, 'bar')); // 'bar-bar'
Вы можете проверить здесь для получения дополнительной информации о регулярных выражениях.
Это происходит потому, что replaceAll
— это новая функция, реализованная не во всех браузерах и более старых версиях Node.js (старше 15.0), как упоминалось в другом ответе. Вы можете увидеть, какие браузеры поддерживают это в Могу ли я использовать:
Но вместо того, чтобы использовать .replace
с RegExp, вы можете добавить полифилл для поддержки старых браузеров (при необходимости). В моем случае я использую Electron, поэтому мне нужно сделать это только для Jest.
Прокладку можно найти здесь.
Установить как зависимость с помощью npm i string.prototype.replaceall
или yarn add string.prototype.replaceall
;
Добавьте следующий код в свой проект. Его нужно добавить только в одном месте.
import replaceAllInserter from 'string.prototype.replaceall';
replaceAllInserter.shim();
Как упоминал @leonheess в комментариях, вы можете обновить Node.js до более новой версии. Вам понадобится версия, которая использует версию 8.5 из V8, когда была реализована .replaceAll
.
Согласно списку , доступному на веб-сайте Node.js , ни одна из версий не использует V8 8.5, но начиная с Node.js 15.0.0 используется версия 8.6 V8. Итак, обновитесь до Node.js v15 или выше.
Если вы хотите решить эту проблему только для Jest, вы можете сделать, как указано в этом выпуске:
Установить как зависимость разработчика с помощью npm i -D string.prototype.replaceall
или yarn add -D string.prototype.replaceall
;
Измените конфигурацию Jest, добавьте свойство setupFilesAfterEnv
, как показано ниже:
{
"jest": {
"setupFilesAfterEnv": ["<rootDir>/jestSetup.js"]
}
}
jestSetup
:import replaceAllInserter from 'string.prototype.replaceall';
replaceAllInserter.shim();
Только для Jest у меня сработало решение polyfill, спасибо.
Вы также можете добавить это в любом месте вашего файла main.js.
if (typeof String.prototype.replaceAll === "undefined") {
String.prototype.replaceAll = function (match, replace) {
return this.replace(new RegExp(match, 'g'), () => replace);
}
}
Это не работает, если match
является реальным регулярным выражением, таким как .
, но я объединил ваш ответ с этим
Вы можете использовать Babel для переноса вашего кода (в ES5), а также разрешить ему внедрять полифиллы там, где это необходимо.
В вашем случае использование метода .replaceAll
не работает, потому что, как объяснено в других ответах, тесты выполняются в версии Node, которая не поддерживает этот метод.
Я не советую делать то, что говорят другие ответчики, потому что они просто решают эту конкретную проблему, но вы можете столкнуться с аналогичными проблемами, если будете использовать другие методы, не поддерживаемые вашей текущей версией Node.
Чтобы гарантировать отсутствие таких проблем, Babel используется вместе с core-js.
Вот важная цитата с этой страницы: https://jestjs.io/docs/getting-started#using-babel
babel-jest
автоматически устанавливается при установке Jest и автоматически преобразует файлы, если в вашем проекте существует конфигурация babel.
Вам также потребуется установить пресет Babel для vue
, чтобы он скомпилировал ваши файлы, специфичные для vue: https://www.npmjs.com/package/@vue/babel-preset-app
Итак, в корневой папке найдите файл конфигурации Babel или создайте его: babel.config.js
(раньше был .babelrc.js
или файл .json
).
Используйте эту конфигурацию:
core-js
и явно укажите минорную версию при его настройке для Babel (см. ниже)useBuiltIns
в @babel/preset-env
, чтобы полифиллы core-js работали.targets
также должен быть указан, поскольку ваши тесты выполняются на узле (а не в вашем браузере). Вы также можете создать для этого файл .browserlist
.module.exports = {
presets: [
['@babel/preset-env', {
"corejs": "3.26",
"useBuiltIns": "usage",
"targets": { "node": "current" }
}],
'@babel/preset-react'],
plugins: [
"@babel/plugin-transform-runtime"
]
};
Интересно прочитать:
И если вам нужно передать какую-то случайную строку. Возможно, HTML-тег с атрибутами. Тогда это становится еще большей проблемой.