matches.js 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.fuzzyMatches = fuzzyMatches;
  6. exports.getDefaultNormalizer = getDefaultNormalizer;
  7. exports.makeNormalizer = makeNormalizer;
  8. exports.matches = matches;
  9. function assertNotNullOrUndefined(matcher) {
  10. if (matcher === null || matcher === undefined) {
  11. throw new Error(
  12. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- implicitly converting `T` to `string`
  13. `It looks like ${matcher} was passed instead of a matcher. Did you do something like getByText(${matcher})?`);
  14. }
  15. }
  16. function fuzzyMatches(textToMatch, node, matcher, normalizer) {
  17. if (typeof textToMatch !== 'string') {
  18. return false;
  19. }
  20. assertNotNullOrUndefined(matcher);
  21. const normalizedText = normalizer(textToMatch);
  22. if (typeof matcher === 'string' || typeof matcher === 'number') {
  23. return normalizedText.toLowerCase().includes(matcher.toString().toLowerCase());
  24. } else if (typeof matcher === 'function') {
  25. return matcher(normalizedText, node);
  26. } else {
  27. return matchRegExp(matcher, normalizedText);
  28. }
  29. }
  30. function matches(textToMatch, node, matcher, normalizer) {
  31. if (typeof textToMatch !== 'string') {
  32. return false;
  33. }
  34. assertNotNullOrUndefined(matcher);
  35. const normalizedText = normalizer(textToMatch);
  36. if (matcher instanceof Function) {
  37. return matcher(normalizedText, node);
  38. } else if (matcher instanceof RegExp) {
  39. return matchRegExp(matcher, normalizedText);
  40. } else {
  41. return normalizedText === String(matcher);
  42. }
  43. }
  44. function getDefaultNormalizer({
  45. trim = true,
  46. collapseWhitespace = true
  47. } = {}) {
  48. return text => {
  49. let normalizedText = text;
  50. normalizedText = trim ? normalizedText.trim() : normalizedText;
  51. normalizedText = collapseWhitespace ? normalizedText.replace(/\s+/g, ' ') : normalizedText;
  52. return normalizedText;
  53. };
  54. }
  55. /**
  56. * Constructs a normalizer to pass to functions in matches.js
  57. * @param {boolean|undefined} trim The user-specified value for `trim`, without
  58. * any defaulting having been applied
  59. * @param {boolean|undefined} collapseWhitespace The user-specified value for
  60. * `collapseWhitespace`, without any defaulting having been applied
  61. * @param {Function|undefined} normalizer The user-specified normalizer
  62. * @returns {Function} A normalizer
  63. */
  64. function makeNormalizer({
  65. trim,
  66. collapseWhitespace,
  67. normalizer
  68. }) {
  69. if (!normalizer) {
  70. // No custom normalizer specified. Just use default.
  71. return getDefaultNormalizer({
  72. trim,
  73. collapseWhitespace
  74. });
  75. }
  76. if (typeof trim !== 'undefined' || typeof collapseWhitespace !== 'undefined') {
  77. // They've also specified a value for trim or collapseWhitespace
  78. throw new Error('trim and collapseWhitespace are not supported with a normalizer. ' + 'If you want to use the default trim and collapseWhitespace logic in your normalizer, ' + 'use "getDefaultNormalizer({trim, collapseWhitespace})" and compose that into your normalizer');
  79. }
  80. return normalizer;
  81. }
  82. function matchRegExp(matcher, text) {
  83. const match = matcher.test(text);
  84. if (matcher.global && matcher.lastIndex !== 0) {
  85. console.warn(`To match all elements we had to reset the lastIndex of the RegExp because the global flag is enabled. We encourage to remove the global flag from the RegExp.`);
  86. matcher.lastIndex = 0;
  87. }
  88. return match;
  89. }