text: 'use strict';
  const espurify = require('espurify');
  const enhance = require('enhance-visitors');
  const deepStrictEqual = require('deep-strict-equal');
  
  const avaImportDeclarationAst = {
  	type: 'ImportDeclaration',
  	specifiers: [
  		{
  			type: 'ImportDefaultSpecifier',
  			local: {
  				type: 'Identifier',
  				name: 'test'
  			}
  		}
  	],
  	source: {
  		type: 'Literal',
  		value: 'ava'
  	}
  };
  
  const avaVariableDeclaratorAst = {
  	type: 'VariableDeclarator',
  	id: {
  		type: 'Identifier',
  		name: 'test'
  	},
  	init: {
  		type: 'CallExpression',
  		callee: {
  			type: 'Identifier',
  			name: 'require'
  		},
  		arguments: [
  			{
  				type: 'Literal',
  				value: 'ava'
  			}
  		]
  	}
  };
  
  function isTestFunctionCall(node) {
  	if (node.type === 'Identifier') {
  		return node.name === 'test';
  	} else if (node.type === 'MemberExpression') {
  		return isTestFunctionCall(node.object);
  	}
  
  	return false;
  }
  
  function hasTestModifier(node, mod) {
  	if (node.type === 'CallExpression') {
  		return hasTestModifier(node.callee, mod);
  	} else if (node.type === 'MemberExpression') {
  		if (node.property.type === 'Identifier' && node.property.name === mod) {
  			return true;
  		}
  
  		return hasTestModifier(node.object, mod);
  	}
  
  	return false;
  }
  
  module.exports = () => {
  	let isTestFile = false;
  	let currentTestNode = null;
  
  	/* eslint quote-props: [2, "as-needed"] */
  	const predefinedRules = {
  		ImportDeclaration: node => {
  			if (!isTestFile && deepStrictEqual(espurify(node), avaImportDeclarationAst)) {
  				isTestFile = true;
  			}
  		},
  		VariableDeclarator: node => {
  			if (!isTestFile && deepStrictEqual(espurify(node), avaVariableDeclaratorAst)) {
  				isTestFile = true;
  			}
  		},
  		CallExpression: node => {
  			if (isTestFunctionCall(node.callee)) {
  				// Entering test function
  				currentTestNode = node;
  			}
  		},
  		'CallExpression:exit': node => {
  			if (currentTestNode === node) {
  				// Leaving test function
  				currentTestNode = null;
  			}
  		},
  		'Program:exit': () => {
  			isTestFile = false;
  		}
  	};
  
  	return {
  		hasTestModifier: mod => hasTestModifier(currentTestNode, mod),
  		hasNoHookModifier: () => !hasTestModifier(currentTestNode, 'before') &&
  				!hasTestModifier(currentTestNode, 'beforeEach') &&
  				!hasTestModifier(currentTestNode, 'after') &&
  				!hasTestModifier(currentTestNode, 'afterEach'),
  		isInTestFile: () => isTestFile,
  		isInTestNode: () => currentTestNode,
  		isTestNode: node => currentTestNode === node,
  		merge: customHandlers => {
  			return enhance.mergeVisitors([predefinedRules, customHandlers]);
  		}
  	};
  };
  