Шутка: TypeError: replaceAll не является функцией

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"
},

Как я могу исправить это поведение?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
54
0
30 315
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Скорее всего, это происходит потому, что 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'

Вы можете проверить здесь для получения дополнительной информации о регулярных выражениях.

И если вам нужно передать какую-то случайную строку. Возможно, HTML-тег с атрибутами. Тогда это становится еще большей проблемой.

Eugene 01.09.2021 19:58
Ответ принят как подходящий

Проблема

Это происходит потому, что replaceAll — это новая функция, реализованная не во всех браузерах и более старых версиях Node.js (старше 15.0), как упоминалось в другом ответе. Вы можете увидеть, какие браузеры поддерживают это в Могу ли я использовать:

Но вместо того, чтобы использовать .replace с RegExp, вы можете добавить полифилл для поддержки старых браузеров (при необходимости). В моем случае я использую Electron, поэтому мне нужно сделать это только для Jest.

Прокладку можно найти здесь.

Решение

Использование в качестве полифилла для браузеров

  1. Установить как зависимость с помощью npm i string.prototype.replaceall или yarn add string.prototype.replaceall;

  2. Добавьте следующий код в свой проект. Его нужно добавить только в одном месте.

import replaceAllInserter from 'string.prototype.replaceall';

replaceAllInserter.shim();

Использование только в Jest

Обновить Node.js

Как упоминал @leonheess в комментариях, вы можете обновить Node.js до более новой версии. Вам понадобится версия, которая использует версию 8.5 из V8, когда была реализована .replaceAll.

Согласно списку , доступному на веб-сайте Node.js , ни одна из версий не использует V8 8.5, но начиная с Node.js 15.0.0 используется версия 8.6 V8. Итак, обновитесь до Node.js v15 или выше.

Использовать как полифилл

Если вы хотите решить эту проблему только для Jest, вы можете сделать, как указано в этом выпуске:

  1. Установить как зависимость разработчика с помощью npm i -D string.prototype.replaceall или yarn add -D string.prototype.replaceall;

  2. Измените конфигурацию Jest, добавьте свойство setupFilesAfterEnv, как показано ниже:

{
  "jest": {
    "setupFilesAfterEnv": ["<rootDir>/jestSetup.js"]
  }
}
  1. Добавьте следующий код в ваш файл jestSetup:
import replaceAllInserter from 'string.prototype.replaceall';

replaceAllInserter.shim();

Только для Jest у меня сработало решение polyfill, спасибо.

Codigo Morsa 03.03.2022 16:00

Вы также можете добавить это в любом месте вашего файла main.js.

if (typeof String.prototype.replaceAll === "undefined") {
  String.prototype.replaceAll = function (match, replace) {
    return this.replace(new RegExp(match, 'g'), () => replace);
  }
}

Это не работает, если match является реальным регулярным выражением, таким как ., но я объединил ваш ответ с этим

MikeL 14.11.2022 13:08

Вы можете использовать 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).

Используйте эту конфигурацию:

  1. обязательно обновите свой пакет core-js и явно укажите минорную версию при его настройке для Babel (см. ниже)
  2. необходимо активировать параметр useBuiltIns в @babel/preset-env, чтобы полифиллы core-js работали.
  3. параметр targets также должен быть указан, поскольку ваши тесты выполняются на узле (а не в вашем браузере). Вы также можете создать для этого файл .browserlist.
module.exports = {
  presets: [
    ['@babel/preset-env', { 
      "corejs": "3.26", 
      "useBuiltIns": "usage", 
      "targets": { "node": "current" } 
    }],
    '@babel/preset-react'],
  plugins: [
    "@babel/plugin-transform-runtime"
  ]
};

Интересно прочитать:

Запуск тестов Mocha 6 ES6 с Babel 7, как настроить?

Другие вопросы по теме