1. 'use strict';
    
  2. 
    
  3. /* eslint-disable no-for-of-loops/no-for-of-loops */
    
  4. 
    
  5. const getComments = require('./getComments');
    
  6. 
    
  7. const GATE_VERSION_STR = '@reactVersion ';
    
  8. const REACT_VERSION_ENV = process.env.REACT_VERSION;
    
  9. 
    
  10. function transform(babel) {
    
  11.   const {types: t} = babel;
    
  12. 
    
  13.   // Runs tests conditionally based on the version of react (semver range) we are running
    
  14.   // Input:
    
  15.   //   @reactVersion >= 17.0
    
  16.   //   test('some test', () => {/*...*/})
    
  17.   //
    
  18.   // Output:
    
  19.   //    @reactVersion >= 17.0
    
  20.   //   _test_react_version('>= 17.0', 'some test', () => {/*...*/});
    
  21.   //
    
  22.   // See info about semver ranges here:
    
  23.   // https://www.npmjs.com/package/semver
    
  24.   function buildGateVersionCondition(comments) {
    
  25.     if (!comments) {
    
  26.       return null;
    
  27.     }
    
  28. 
    
  29.     const resultingCondition = comments.reduce(
    
  30.       (accumulatedCondition, commentLine) => {
    
  31.         const commentStr = commentLine.value.trim();
    
  32. 
    
  33.         if (!commentStr.startsWith(GATE_VERSION_STR)) {
    
  34.           return accumulatedCondition;
    
  35.         }
    
  36. 
    
  37.         const condition = commentStr.slice(GATE_VERSION_STR.length);
    
  38.         if (accumulatedCondition === null) {
    
  39.           return condition;
    
  40.         }
    
  41. 
    
  42.         return accumulatedCondition.concat(' ', condition);
    
  43.       },
    
  44.       null
    
  45.     );
    
  46. 
    
  47.     if (resultingCondition === null) {
    
  48.       return null;
    
  49.     }
    
  50. 
    
  51.     return t.stringLiteral(resultingCondition);
    
  52.   }
    
  53. 
    
  54.   return {
    
  55.     name: 'transform-react-version-pragma',
    
  56.     visitor: {
    
  57.       ExpressionStatement(path) {
    
  58.         const statement = path.node;
    
  59.         const expression = statement.expression;
    
  60.         if (expression.type === 'CallExpression') {
    
  61.           const callee = expression.callee;
    
  62.           switch (callee.type) {
    
  63.             case 'Identifier': {
    
  64.               if (
    
  65.                 callee.name === 'test' ||
    
  66.                 callee.name === 'it' ||
    
  67.                 callee.name === 'fit'
    
  68.               ) {
    
  69.                 const comments = getComments(path);
    
  70.                 const condition = buildGateVersionCondition(comments);
    
  71.                 if (condition !== null) {
    
  72.                   callee.name =
    
  73.                     callee.name === 'fit'
    
  74.                       ? '_test_react_version_focus'
    
  75.                       : '_test_react_version';
    
  76.                   expression.arguments = [condition, ...expression.arguments];
    
  77.                 } else if (REACT_VERSION_ENV) {
    
  78.                   callee.name = '_test_ignore_for_react_version';
    
  79.                 }
    
  80.               }
    
  81.               break;
    
  82.             }
    
  83.             case 'MemberExpression': {
    
  84.               if (
    
  85.                 callee.object.type === 'Identifier' &&
    
  86.                 (callee.object.name === 'test' ||
    
  87.                   callee.object.name === 'it') &&
    
  88.                 callee.property.type === 'Identifier' &&
    
  89.                 callee.property.name === 'only'
    
  90.               ) {
    
  91.                 const comments = getComments(path);
    
  92.                 const condition = buildGateVersionCondition(comments);
    
  93.                 if (condition !== null) {
    
  94.                   statement.expression = t.callExpression(
    
  95.                     t.identifier('_test_react_version_focus'),
    
  96.                     [condition, ...expression.arguments]
    
  97.                   );
    
  98.                 } else if (REACT_VERSION_ENV) {
    
  99.                   statement.expression = t.callExpression(
    
  100.                     t.identifier('_test_ignore_for_react_version'),
    
  101.                     expression.arguments
    
  102.                   );
    
  103.                 }
    
  104.               }
    
  105.               break;
    
  106.             }
    
  107.           }
    
  108.         }
    
  109.         return;
    
  110.       },
    
  111.     },
    
  112.   };
    
  113. }
    
  114. 
    
  115. module.exports = transform;