mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
fix(internal): Add locus resloving capabilities
Resolve all Meteor.isClient, Meteor.isServer and Meteor.isCordova LogicalExpressions
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import getMeta from './util/getMeta'
|
||||
import {getMeta} from './util'
|
||||
|
||||
function unpack (rule) {
|
||||
const packedRule = require(rule)
|
||||
|
||||
@@ -10,7 +10,9 @@ import {isMeteorCall, isFunction} from '../util/ast'
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
module.exports = () => (context) => {
|
||||
module.exports = getMeta => context => {
|
||||
|
||||
const {isLintedEnv} = getMeta(context.getFilename())
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -57,6 +59,10 @@ module.exports = () => (context) => {
|
||||
// Public
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
CallExpression: (node) => {
|
||||
|
||||
|
||||
@@ -9,16 +9,11 @@
|
||||
// Rule Definition
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
import {CLIENT, SERVER, UNIVERSAL} from '../util/environment'
|
||||
import {isMeteorProp, isMeteorCall} from '../util/ast'
|
||||
|
||||
module.exports = getMeta => context => {
|
||||
|
||||
const {env} = getMeta(context.getFilename())
|
||||
|
||||
if (env !== CLIENT && env !== SERVER && env !== UNIVERSAL) {
|
||||
return {}
|
||||
}
|
||||
const {isLintedEnv} = getMeta(context.getFilename())
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -43,6 +38,10 @@ module.exports = getMeta => context => {
|
||||
// Public
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
AssignmentExpression: function (node) {
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
// Rule Definition
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
module.exports = () => (context) => {
|
||||
module.exports = getMeta => context => {
|
||||
|
||||
const {isLintedEnv} = getMeta(context.getFilename())
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -41,6 +43,10 @@ module.exports = () => (context) => {
|
||||
// Public
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
AssignmentExpression: (node) => {
|
||||
|
||||
@@ -6,18 +6,23 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
// -----------------------------------------------------------------------------
|
||||
module.exports = getMeta => context => {
|
||||
|
||||
module.exports = () => context => {
|
||||
const {isLintedEnv} = getMeta(context.getFilename())
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
MemberExpression (node) {
|
||||
if (node.object.name === 'Session') {
|
||||
context.report(node, 'Unexpected Session statement.')
|
||||
context.report(node, 'Unexpected Session statement')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,18 @@ import {isMeteorCall} from '../util/ast'
|
||||
// Rule Definition
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
module.exports = () => (context) => {
|
||||
module.exports = getMeta => context => {
|
||||
|
||||
const {isLintedEnv} = getMeta(context.getFilename())
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
CallExpression: function (node) {
|
||||
|
||||
@@ -5,19 +5,16 @@
|
||||
* See LICENSE file in root directory for full license.
|
||||
*/
|
||||
|
||||
import {CLIENT, SERVER, UNIVERSAL} from '../util/environment'
|
||||
import {isMeteorCall, isInServerBlock, isInClientBlock} from '../util/ast'
|
||||
import {isMeteorCall} from '../util/ast'
|
||||
import {getExecutors} from '../util'
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
module.exports = getMeta => context => {
|
||||
const {env} = getMeta(context.getFilename())
|
||||
|
||||
if (env !== CLIENT && env !== SERVER && env !== UNIVERSAL) {
|
||||
return {}
|
||||
}
|
||||
const {isLintedEnv, env} = getMeta(context.getFilename())
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -43,62 +40,50 @@ module.exports = getMeta => context => {
|
||||
context.report(node, 'Allowed on client only')
|
||||
}
|
||||
|
||||
function checkMeteorPublish (node, ancestors) {
|
||||
function checkMeteorPublish (node, executors) {
|
||||
if (!isMeteorCall(node, 'publish')) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (env) {
|
||||
case CLIENT:
|
||||
noPublishOnClient(node)
|
||||
break
|
||||
case SERVER:
|
||||
expectTwoArguments(node)
|
||||
break
|
||||
case UNIVERSAL:
|
||||
if (isInServerBlock(ancestors)) {
|
||||
expectTwoArguments(node)
|
||||
} else {
|
||||
noPublishOnClient(node)
|
||||
}
|
||||
break
|
||||
if (executors.has('browser')) {
|
||||
noPublishOnClient(node)
|
||||
}
|
||||
|
||||
if (executors.has('server')) {
|
||||
expectTwoArguments(node)
|
||||
}
|
||||
}
|
||||
|
||||
function checkMeteorSubscribe (node, ancestors) {
|
||||
function checkMeteorSubscribe (node, executors) {
|
||||
if (!isMeteorCall(node, 'subscribe')) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (env) {
|
||||
case CLIENT:
|
||||
atLeastOneArgument(node)
|
||||
break
|
||||
case SERVER:
|
||||
noSubscribeOnServer(node)
|
||||
break
|
||||
case UNIVERSAL:
|
||||
if (isInClientBlock(ancestors)) {
|
||||
atLeastOneArgument(node)
|
||||
} else {
|
||||
noSubscribeOnServer(node)
|
||||
}
|
||||
break
|
||||
if (executors.has('browser')) {
|
||||
atLeastOneArgument(node)
|
||||
}
|
||||
if (executors.has('server')) {
|
||||
noSubscribeOnServer(node)
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
// Public
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
CallExpression: function (node) {
|
||||
|
||||
const ancestors = context.getAncestors()
|
||||
const executors = getExecutors(env, ancestors)
|
||||
|
||||
// Meteor.publish
|
||||
checkMeteorPublish(node, ancestors)
|
||||
checkMeteorSubscribe(node, ancestors)
|
||||
checkMeteorPublish(node, executors)
|
||||
checkMeteorSubscribe(node, executors)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export {default as isMeteorCall} from './isMeteorCall'
|
||||
export {default as isMeteorProp} from './isMeteorProp'
|
||||
export {default as isInBlock, isInClientBlock, isInServerBlock} from './isInBlock'
|
||||
export {default as isFunction} from './isFunction'
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import {CLIENT, SERVER} from '../environment'
|
||||
import isMeteorProp from './isMeteorProp'
|
||||
import invariant from 'invariant'
|
||||
|
||||
export function isInBlock (ancestors, env) {
|
||||
|
||||
invariant(Array.isArray(ancestors), 'isInBlock: ancestors is not an array')
|
||||
invariant(!!env, 'isInBlock: called without environment')
|
||||
invariant(env === CLIENT || env === SERVER, 'isInBlock: unkown environment')
|
||||
|
||||
if (ancestors.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
let isInServer = false
|
||||
let isInClient = false
|
||||
for (let i = 0; i < ancestors.length; i++) {
|
||||
const ancestor = ancestors[i]
|
||||
|
||||
if (ancestor.type === 'IfStatement' && ancestor.test.type === 'MemberExpression') {
|
||||
if (isMeteorProp(ancestor.test, 'isServer')) {
|
||||
isInServer = true
|
||||
}
|
||||
if (isMeteorProp(ancestor.test, 'isClient')) {
|
||||
isInClient = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (env) {
|
||||
case SERVER:
|
||||
return isInServer && !isInClient
|
||||
case CLIENT:
|
||||
return !isInServer && isInClient
|
||||
}
|
||||
}
|
||||
|
||||
export function isInServerBlock (ancestors) {
|
||||
return isInBlock(ancestors, SERVER)
|
||||
}
|
||||
|
||||
export function isInClientBlock (ancestors) {
|
||||
return isInBlock(ancestors, CLIENT)
|
||||
}
|
||||
33
lib/util/executors/filterExecutorsByAncestors.js
Normal file
33
lib/util/executors/filterExecutorsByAncestors.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import invariant from 'invariant'
|
||||
import isMeteorBlockOnlyTest from './isMeteorBlockOnlyTest'
|
||||
import getExecutorsFromTest from './getExecutorsFromTest'
|
||||
import {intersection, difference} from './sets'
|
||||
|
||||
// Set -> Array -> Set
|
||||
export default function filterExecutorsByAncestors (originalExecutors, ancestors) {
|
||||
|
||||
let executors = new Set([...originalExecutors])
|
||||
|
||||
for (let i = ancestors.length - 1; i > 0; i--) {
|
||||
const current = ancestors[i]
|
||||
const parent = ancestors[i - 1]
|
||||
if (parent.type === 'IfStatement') {
|
||||
if (isMeteorBlockOnlyTest(parent.test)) {
|
||||
const executorsFromTest = getExecutorsFromTest(parent.test)
|
||||
if (parent.consequent === current) {
|
||||
executors = intersection(executors, executorsFromTest)
|
||||
} else if (parent.alternate === current) {
|
||||
executors = difference(executors, executorsFromTest)
|
||||
} else {
|
||||
invariant(false, 'Block is neither consequent nor alternate of parent')
|
||||
}
|
||||
} else {
|
||||
|
||||
// can not determine executors, because of unresolvable if-statement
|
||||
return new Set()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return executors
|
||||
}
|
||||
10
lib/util/executors/getExecutors.js
Normal file
10
lib/util/executors/getExecutors.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import filterExecutorsByAncestors from './filterExecutorsByAncestors'
|
||||
import getExecutorsByEnv from './getExecutorsByEnv'
|
||||
|
||||
// ENVIRONMENT -> Nodes -> Set
|
||||
export default function getExecutors (env, ancestors) {
|
||||
return filterExecutorsByAncestors(
|
||||
getExecutorsByEnv(env),
|
||||
ancestors
|
||||
)
|
||||
}
|
||||
51
lib/util/executors/getExecutorsByEnv.js
Normal file
51
lib/util/executors/getExecutorsByEnv.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import {
|
||||
PUBLIC,
|
||||
PRIVATE,
|
||||
CLIENT,
|
||||
SERVER,
|
||||
PACKAGE,
|
||||
TEST,
|
||||
NODE_MODULE,
|
||||
UNIVERSAL,
|
||||
PACKAGE_CONFIG,
|
||||
MOBILE_CONFIG,
|
||||
COMPATIBILITY,
|
||||
NON_METEOR
|
||||
} from '../environment'
|
||||
|
||||
/**
|
||||
* Transforms an environment into executors
|
||||
* @param {ENVIRONMENT} env An Environment
|
||||
* @return {Set} A Set of executors
|
||||
*/
|
||||
export default function getExecutorsByEnv (env) {
|
||||
const executors = new Set()
|
||||
switch (env) {
|
||||
case CLIENT:
|
||||
case COMPATIBILITY:
|
||||
executors.add('browser')
|
||||
executors.add('cordova')
|
||||
break
|
||||
case SERVER:
|
||||
executors.add('server')
|
||||
break
|
||||
case UNIVERSAL:
|
||||
executors.add('server')
|
||||
executors.add('browser')
|
||||
executors.add('cordova')
|
||||
break
|
||||
case PACKAGE_CONFIG:
|
||||
case MOBILE_CONFIG:
|
||||
executors.add('isobuild')
|
||||
break
|
||||
case PUBLIC:
|
||||
case PRIVATE:
|
||||
case TEST:
|
||||
case NODE_MODULE:
|
||||
case NON_METEOR:
|
||||
case PACKAGE:
|
||||
default:
|
||||
break
|
||||
}
|
||||
return executors
|
||||
}
|
||||
28
lib/util/executors/getExecutorsFromTest.js
Normal file
28
lib/util/executors/getExecutorsFromTest.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import invariant from 'invariant'
|
||||
import isMeteorProp from '../ast/isMeteorProp'
|
||||
import {union, intersection} from './sets'
|
||||
import invert from './invert'
|
||||
|
||||
// Nodes -> Set
|
||||
export default function getExecutorsFromTest (test) {
|
||||
switch (test.type) {
|
||||
case 'MemberExpression':
|
||||
if (isMeteorProp(test, 'isClient')) {
|
||||
return new Set(['browser', 'cordova'])
|
||||
} else if (isMeteorProp(test, 'isServer')) {
|
||||
return new Set(['server'])
|
||||
} else if (isMeteorProp(test, 'isCordova')) {
|
||||
return new Set(['cordova'])
|
||||
}
|
||||
return invariant(false, 'Unkown Meteor prop should never be reached')
|
||||
case 'UnaryExpression':
|
||||
return invert(getExecutorsFromTest(test.argument))
|
||||
case 'LogicalExpression':
|
||||
if (test.operator === '&&') {
|
||||
return intersection(getExecutorsFromTest(test.left), getExecutorsFromTest(test.right))
|
||||
} else if (test.operator === '||') {
|
||||
return union(getExecutorsFromTest(test.left), getExecutorsFromTest(test.right))
|
||||
}
|
||||
return invariant(false, 'Unkown operator should never be reached')
|
||||
}
|
||||
}
|
||||
5
lib/util/executors/invert.js
Normal file
5
lib/util/executors/invert.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import {difference} from './sets'
|
||||
|
||||
export default function invert (executors) {
|
||||
return difference(new Set(['browser', 'server', 'cordova']), executors)
|
||||
}
|
||||
28
lib/util/executors/isMeteorBlockOnlyTest.js
Normal file
28
lib/util/executors/isMeteorBlockOnlyTest.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import {isMeteorProp} from '../ast'
|
||||
|
||||
/**
|
||||
* Verifies a test of an IfStatement contains only checks with
|
||||
* Meteor.isClient, Meteor.isServer and Meteor.isCordova.
|
||||
*
|
||||
* @param {node} test Test of an IfStatement (MemberExpression, LogicalExpression, UnaryExpression)
|
||||
* @return {Boolean} True if test contains only Meteor locus checks
|
||||
*/
|
||||
export default function isMeteorBlockOnlyTest (test) {
|
||||
switch (test.type) {
|
||||
case 'MemberExpression':
|
||||
return (
|
||||
isMeteorProp(test, 'isClient') ||
|
||||
isMeteorProp(test, 'isServer') ||
|
||||
isMeteorProp(test, 'isCordova')
|
||||
)
|
||||
case 'UnaryExpression':
|
||||
if (test.operator === '!') {
|
||||
return isMeteorBlockOnlyTest(test.argument)
|
||||
}
|
||||
return false
|
||||
case 'LogicalExpression':
|
||||
return isMeteorBlockOnlyTest(test.left) && isMeteorBlockOnlyTest(test.right)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
26
lib/util/executors/sets.js
Normal file
26
lib/util/executors/sets.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import invariant from 'invariant'
|
||||
|
||||
// Set -> Set -> Set
|
||||
export function difference (a, b) {
|
||||
invariant(!!a, 'difference: Set a is not defined')
|
||||
invariant(!!b, 'difference: Set b is not defined')
|
||||
return new Set(
|
||||
[...a].filter(x => !b.has(x))
|
||||
)
|
||||
}
|
||||
|
||||
// Set -> Set -> Set
|
||||
export function union (a, b) {
|
||||
invariant(!!a, 'union: Set a is not defined')
|
||||
invariant(!!b, 'union: Set b is not defined')
|
||||
return new Set([...a, ...b])
|
||||
}
|
||||
|
||||
// Set -> Set -> Set
|
||||
export function intersection (a, b) {
|
||||
invariant(!!a, 'intersection: Set a is not defined')
|
||||
invariant(!!b, 'intersection: Set b is not defined')
|
||||
return new Set(
|
||||
[...a].filter(element => b.has(element))
|
||||
)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import getMeteorMeta from './internal/getMeteorMeta'
|
||||
const getRelativePath = require('./internal/getRelativePath')
|
||||
|
||||
export default function (filename) {
|
||||
return getMeteorMeta(getRelativePath(filename))
|
||||
}
|
||||
2
lib/util/index.js
Normal file
2
lib/util/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export {default as getMeta} from './meta/getMeta'
|
||||
export {default as getExecutors} from './executors/getExecutors'
|
||||
6
lib/util/meta/getMeta.js
Normal file
6
lib/util/meta/getMeta.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import getMeteorMeta from './getMeteorMeta'
|
||||
const getRelativePath = require('./getRelativePath')
|
||||
|
||||
export default function (filename) {
|
||||
return getMeteorMeta(getRelativePath(filename))
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import path from 'path'
|
||||
import ENVIRONMENT from '../environment.js'
|
||||
import folderNames from '../folderNames.js'
|
||||
import ENVIRONMENT from '../environment'
|
||||
import folderNames from '../folderNames'
|
||||
import isLintedEnv from './isLintedEnv'
|
||||
|
||||
function matchLeft (dirs, list) {
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
@@ -83,14 +84,14 @@ function determineEnvironment (pathInProjectList) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getMeteorFileInfo (relativeFilename) {
|
||||
const pathInProjectList = relativeFilename.split(path.sep)
|
||||
const environment = determineEnvironment(pathInProjectList)
|
||||
|
||||
return {
|
||||
path: relativeFilename,
|
||||
env: environment
|
||||
env: environment,
|
||||
isLintedEnv: isLintedEnv(environment)
|
||||
}
|
||||
}
|
||||
|
||||
5
lib/util/meta/isLintedEnv.js
Normal file
5
lib/util/meta/isLintedEnv.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import {CLIENT, SERVER, UNIVERSAL, COMPATIBILITY} from '../environment'
|
||||
|
||||
export default function (env) {
|
||||
return env === CLIENT || env === SERVER || env === UNIVERSAL || env === COMPATIBILITY
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "Meteor specific linting rules for ESLint",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "babel lib -d dist --auxiliary-comment-before \"istanbul ignore next\"",
|
||||
"build": "babel lib -d dist --optional runtime --auxiliary-comment-before \"istanbul ignore next\"",
|
||||
"build:w": "npm run build -- -w",
|
||||
"check-coverage": "istanbul check-coverage",
|
||||
"clean": "rimraf dist",
|
||||
@@ -36,6 +36,7 @@
|
||||
"devDependencies": {
|
||||
"babel": "5.8.23",
|
||||
"babel-eslint": "4.1.3",
|
||||
"babel-runtime": "5.8.25",
|
||||
"colors": "1.1.2",
|
||||
"coveralls": "2.11.4",
|
||||
"cz-conventional-changelog": "1.1.4",
|
||||
|
||||
@@ -66,11 +66,7 @@ import {CLIENT, SERVER, UNIVERSAL} from '../util/environment'
|
||||
|
||||
module.exports = getMeta => context => {
|
||||
|
||||
const {env} = getMeta(context.getFilename())
|
||||
|
||||
if (env !== CLIENT && env !== SERVER && env !== UNIVERSAL) {
|
||||
return {}
|
||||
}
|
||||
const {isLintedEnv} = getMeta(context.getFilename())
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -82,6 +78,10 @@ module.exports = getMeta => context => {
|
||||
// Public
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
if (!isLintedEnv) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
// give me methods
|
||||
@@ -107,7 +107,7 @@ const test = `/**
|
||||
// Requirements
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
import {CLIENT, SERVER} from '../../../dist/util/environment.js'
|
||||
import {CLIENT, SERVER} from '../../../dist/util/environment'
|
||||
const rule = require('../../../dist/rules/${ruleId}')
|
||||
const RuleTester = require('eslint').RuleTester
|
||||
|
||||
@@ -117,7 +117,7 @@ const RuleTester = require('eslint').RuleTester
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('${ruleId}', rule(() => ({env: SERVER})), {
|
||||
ruleTester.run('${ruleId}', rule(() => ({env: SERVER, isLintedEnv: true})), {
|
||||
|
||||
valid: [
|
||||
// fill me in
|
||||
@@ -127,14 +127,14 @@ ruleTester.run('${ruleId}', rule(() => ({env: SERVER})), {
|
||||
{
|
||||
code: '${escapedFailingExample}',
|
||||
errors: [
|
||||
{message: 'Unexpected Session statement.', type: 'MemberExpression'}
|
||||
{message: 'The error message', type: 'MemberExpression'}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
})
|
||||
|
||||
ruleTester.run('${ruleId}', rule(() => ({env: CLIENT})), {
|
||||
ruleTester.run('${ruleId}', rule(() => ({env: CLIENT, isLintedEnv: true})), {
|
||||
|
||||
valid: [
|
||||
// fill me in
|
||||
|
||||
@@ -16,7 +16,7 @@ const RuleTester = require('eslint').RuleTester
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('audit-argument-checks', rule(), {
|
||||
ruleTester.run('audit-argument-checks', rule(() => ({isLintedEnv: true})), {
|
||||
|
||||
valid: [
|
||||
'foo()',
|
||||
@@ -123,3 +123,10 @@ ruleTester.run('audit-argument-checks', rule(), {
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
ruleTester.run('audit-argument-checks', rule(() => ({isLintedEnv: false})), {
|
||||
valid: [
|
||||
'Meteor.publish("foo", function (bar) { foo(); })'
|
||||
],
|
||||
invalid: []
|
||||
})
|
||||
|
||||
@@ -9,15 +9,6 @@
|
||||
// Requirements
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
import {
|
||||
CLIENT,
|
||||
SERVER,
|
||||
UNIVERSAL,
|
||||
MOBILE_CONFIG,
|
||||
PACKAGE_CONFIG,
|
||||
NON_METEOR
|
||||
} from '../../../dist/util/environment.js'
|
||||
|
||||
const rule = require('../../../dist/rules/core')
|
||||
const RuleTester = require('eslint').RuleTester
|
||||
|
||||
@@ -126,10 +117,5 @@ const errorFreeTests = {
|
||||
}
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('core', rule(() => ({env: SERVER})), tests)
|
||||
ruleTester.run('core', rule(() => ({env: CLIENT})), tests)
|
||||
ruleTester.run('core', rule(() => ({env: UNIVERSAL})), tests)
|
||||
|
||||
ruleTester.run('core', rule(() => ({env: NON_METEOR})), errorFreeTests)
|
||||
ruleTester.run('core', rule(() => ({env: PACKAGE_CONFIG})), errorFreeTests)
|
||||
ruleTester.run('core', rule(() => ({env: MOBILE_CONFIG})), errorFreeTests)
|
||||
ruleTester.run('core', rule(() => ({isLintedEnv: true})), tests)
|
||||
ruleTester.run('core', rule(() => ({isLintedEnv: false})), errorFreeTests)
|
||||
|
||||
@@ -18,7 +18,7 @@ const RuleTester = require('eslint').RuleTester
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('no-blaze-lifecycle-assignment', rule(), {
|
||||
ruleTester.run('no-blaze-lifecycle-assignment', rule(() => ({isLintedEnv: true})), {
|
||||
|
||||
valid: [
|
||||
'x += 1',
|
||||
@@ -74,3 +74,10 @@ ruleTester.run('no-blaze-lifecycle-assignment', rule(), {
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
ruleTester.run('no-blaze-lifecycle-assignment', rule(() => ({isLintedEnv: false})), {
|
||||
valid: [
|
||||
'Template.foo.created = function () {}'
|
||||
],
|
||||
invalid: []
|
||||
})
|
||||
|
||||
@@ -9,37 +9,16 @@
|
||||
// Requirements
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
import {SERVER, CLIENT} from '../../../dist/util/environment.js'
|
||||
const rule = require('../../../dist/rules/no-session')
|
||||
const RuleTester = require('eslint').RuleTester
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Environments
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const serverEnv = {
|
||||
path: 'server/methods.js',
|
||||
env: SERVER,
|
||||
isCompatibilityFile: false,
|
||||
isInMeteorProject: true
|
||||
}
|
||||
|
||||
const clientEnv = {
|
||||
path: 'client/methods.js',
|
||||
env: CLIENT,
|
||||
isCompatibilityFile: false,
|
||||
isInMeteorProject: true
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Tests
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('no-session', rule(() => serverEnv), {
|
||||
ruleTester.run('no-session', rule(() => ({isLintedEnv: true})), {
|
||||
|
||||
valid: [
|
||||
'session.get("foo")',
|
||||
@@ -47,26 +26,17 @@ ruleTester.run('no-session', rule(() => serverEnv), {
|
||||
],
|
||||
|
||||
invalid: [
|
||||
{code: 'Session.set("foo", true)', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]},
|
||||
{code: 'Session.get("foo")', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]},
|
||||
{code: 'Session.clear("foo")', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]},
|
||||
{code: 'Session.all()', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]}
|
||||
{code: 'Session.set("foo", true)', errors: [{message: 'Unexpected Session statement', type: 'MemberExpression'}]},
|
||||
{code: 'Session.get("foo")', errors: [{message: 'Unexpected Session statement', type: 'MemberExpression'}]},
|
||||
{code: 'Session.clear("foo")', errors: [{message: 'Unexpected Session statement', type: 'MemberExpression'}]},
|
||||
{code: 'Session.all()', errors: [{message: 'Unexpected Session statement', type: 'MemberExpression'}]}
|
||||
]
|
||||
|
||||
})
|
||||
|
||||
ruleTester.run('no-session', rule(() => clientEnv), {
|
||||
|
||||
ruleTester.run('no-session', rule(() => ({isLintedEnv: false})), {
|
||||
valid: [
|
||||
'session.get("foo")',
|
||||
'foo(Session)'
|
||||
'Session.set("foo", true)',
|
||||
'Session.get("foo")'
|
||||
],
|
||||
|
||||
invalid: [
|
||||
{code: 'Session.set("foo", true)', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]},
|
||||
{code: 'Session.get("foo")', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]},
|
||||
{code: 'Session.clear("foo")', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]},
|
||||
{code: 'Session.all()', errors: [{message: 'Unexpected Session statement.', type: 'MemberExpression'}]}
|
||||
]
|
||||
|
||||
invalid: []
|
||||
})
|
||||
|
||||
@@ -16,7 +16,7 @@ const RuleTester = require('eslint').RuleTester
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('no-zero-timeout', rule(), {
|
||||
ruleTester.run('no-zero-timeout', rule(() => ({isLintedEnv: true})), {
|
||||
|
||||
valid: [
|
||||
'Meteor.setTimeout()',
|
||||
@@ -66,3 +66,10 @@ ruleTester.run('no-zero-timeout', rule(), {
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
ruleTester.run('no-zero-timeout', rule(() => ({isLintedEnv: false})), {
|
||||
valid: [
|
||||
'Meteor.setTimeout(function () {}, 0)'
|
||||
],
|
||||
invalid: []
|
||||
})
|
||||
|
||||
@@ -13,49 +13,12 @@ import {CLIENT, SERVER, UNIVERSAL} from '../../../dist/util/environment.js'
|
||||
const rule = require('../../../dist/rules/pubsub')
|
||||
const RuleTester = require('eslint').RuleTester
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Environments
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const serverEnv = {
|
||||
path: 'server/pubsub.js',
|
||||
env: SERVER,
|
||||
isCompatibilityFile: false,
|
||||
isInMeteorProject: true,
|
||||
isPackageConfig: false,
|
||||
isMobileConfig: false
|
||||
}
|
||||
|
||||
const clientEnv = {
|
||||
path: 'server/pubsub.js',
|
||||
env: CLIENT,
|
||||
isCompatibilityFile: false,
|
||||
isInMeteorProject: true,
|
||||
isPackageConfig: false,
|
||||
isMobileConfig: false
|
||||
}
|
||||
|
||||
const universalEnv = {
|
||||
path: 'pubsub.js',
|
||||
env: UNIVERSAL,
|
||||
isCompatibilityFile: false,
|
||||
isInMeteorProject: true,
|
||||
isPackageConfig: false,
|
||||
isMobileConfig: false
|
||||
}
|
||||
|
||||
const notInMeteorProject = {
|
||||
isInMeteorProject: false
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Tests
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
const ruleTester = new RuleTester()
|
||||
ruleTester.run('pubsub', rule(() => serverEnv), {
|
||||
ruleTester.run('pubsub', rule(() => ({env: SERVER, isLintedEnv: true})), {
|
||||
valid: [
|
||||
'Meteor.publish("foo", function () {})'
|
||||
],
|
||||
@@ -76,7 +39,7 @@ ruleTester.run('pubsub', rule(() => serverEnv), {
|
||||
]
|
||||
})
|
||||
|
||||
ruleTester.run('pubsub', rule(() => clientEnv), {
|
||||
ruleTester.run('pubsub', rule(() => ({env: CLIENT, isLintedEnv: true})), {
|
||||
valid: [
|
||||
'Meteor.subscribe("foo")'
|
||||
],
|
||||
@@ -97,10 +60,20 @@ ruleTester.run('pubsub', rule(() => clientEnv), {
|
||||
]
|
||||
})
|
||||
|
||||
ruleTester.run('pubsub', rule(() => universalEnv), {
|
||||
ruleTester.run('pubsub', rule(() => ({env: UNIVERSAL, isLintedEnv: true})), {
|
||||
valid: [
|
||||
'if (Meteor.isClient) { Meteor.subscribe("foo") }',
|
||||
'if (Meteor.isServer) { Meteor.publish("foo", function () {}) }'
|
||||
'if (Meteor.isServer) { Meteor.publish("foo", function () {}) }',
|
||||
`
|
||||
if (Meteor.isClient) {
|
||||
if (Meteor.isServer) {
|
||||
|
||||
// valid because it is unreachable
|
||||
Meteor.publish("foo", function () {})
|
||||
Meteor.subscribe("foo")
|
||||
}
|
||||
}
|
||||
`
|
||||
],
|
||||
|
||||
invalid: [
|
||||
@@ -109,39 +82,11 @@ ruleTester.run('pubsub', rule(() => universalEnv), {
|
||||
errors: [
|
||||
{message: 'Allowed on client only', type: 'CallExpression'}
|
||||
]
|
||||
},
|
||||
{
|
||||
code: `
|
||||
if (Meteor.isClient) {
|
||||
if (Meteor.isServer) {
|
||||
Meteor.publish("foo", function () {})
|
||||
Meteor.subscribe("foo")
|
||||
}
|
||||
}
|
||||
`,
|
||||
errors: [
|
||||
{message: 'Allowed on server only', type: 'CallExpression'},
|
||||
{message: 'Allowed on client only', type: 'CallExpression'}
|
||||
]
|
||||
},
|
||||
{
|
||||
code: `
|
||||
if (Meteor.isServer) {
|
||||
if (Meteor.isClient) {
|
||||
Meteor.publish("foo", function () {})
|
||||
Meteor.subscribe("foo")
|
||||
}
|
||||
}
|
||||
`,
|
||||
errors: [
|
||||
{message: 'Allowed on server only', type: 'CallExpression'},
|
||||
{message: 'Allowed on client only', type: 'CallExpression'}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
ruleTester.run('pubsub', rule(() => notInMeteorProject), {
|
||||
ruleTester.run('pubsub', rule(() => ({isLintedEnv: false})), {
|
||||
valid: [
|
||||
'foo()'
|
||||
],
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import {CLIENT, SERVER, UNIVERSAL} from '../../../../dist/util/environment'
|
||||
import {isInBlock, isInServerBlock, isInClientBlock} from '../../../../dist/util/ast/isInBlock'
|
||||
|
||||
describe('isInBlock', function () {
|
||||
it('returns false if no ancestors are present', function () {
|
||||
assert.equal(isInBlock([], CLIENT), false)
|
||||
assert.equal(isInBlock([], SERVER), false)
|
||||
})
|
||||
|
||||
it('throws if no ancestors are given', function () {
|
||||
assert.throws(isInClientBlock, Error)
|
||||
assert.throws(isInServerBlock, Error)
|
||||
})
|
||||
|
||||
it('throws if no environment is given', function () {
|
||||
assert.throws(isInBlock.bind(null, []), Error)
|
||||
})
|
||||
|
||||
it('throws when called with unhandeled environment', function () {
|
||||
assert.throws(isInBlock.bind(null, [], UNIVERSAL))
|
||||
})
|
||||
})
|
||||
190
tests/lib/util/executors/filterExecutorsByAncestors.js
Normal file
190
tests/lib/util/executors/filterExecutorsByAncestors.js
Normal file
@@ -0,0 +1,190 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import filterExecutorsByAncestors from '../../../../dist/util/executors/filterExecutorsByAncestors'
|
||||
|
||||
describe('filterExecutorsByAncestors', function () {
|
||||
|
||||
it('filters on MemberExpression for isClient', function () {
|
||||
const consequent = {type: 'BlockStatement'}
|
||||
const result = filterExecutorsByAncestors(new Set(['browser', 'server']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
},
|
||||
consequent: consequent
|
||||
},
|
||||
consequent
|
||||
])
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('browser'))
|
||||
})
|
||||
|
||||
it('filters on MemberExpression for else-block of isClient', function () {
|
||||
const alternate = {type: 'BlockStatement'}
|
||||
const result = filterExecutorsByAncestors(new Set(['browser', 'server']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
},
|
||||
alternate: alternate
|
||||
},
|
||||
alternate
|
||||
])
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('server'))
|
||||
})
|
||||
|
||||
it('warns on hierarchical error', function () {
|
||||
assert.throws(() => {
|
||||
const consequent = {type: 'BlockStatement'}
|
||||
filterExecutorsByAncestors(new Set(['browser', 'server']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
}
|
||||
},
|
||||
consequent
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
it('filters on MemberExpression for isServer', function () {
|
||||
const consequent = {type: 'BlockStatement'}
|
||||
const result = filterExecutorsByAncestors(new Set(['server', 'cordova']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
},
|
||||
consequent: consequent
|
||||
},
|
||||
consequent
|
||||
])
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('server'))
|
||||
})
|
||||
|
||||
it('filters on MemberExpression for isCordova', function () {
|
||||
const consequent = {type: 'BlockStatement'}
|
||||
const result = filterExecutorsByAncestors(new Set(['browser', 'cordova']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isCordova'
|
||||
}
|
||||
},
|
||||
consequent: consequent
|
||||
},
|
||||
consequent
|
||||
])
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
|
||||
it('filters on UnaryExpression', function () {
|
||||
const consequent = {type: 'BlockStatement'}
|
||||
const result = filterExecutorsByAncestors(new Set(['browser', 'server', 'cordova']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {
|
||||
type: 'UnaryExpression',
|
||||
operator: '!',
|
||||
argument: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
}
|
||||
},
|
||||
consequent: consequent
|
||||
},
|
||||
consequent
|
||||
])
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('server'))
|
||||
})
|
||||
|
||||
it('returns no executors when an unresolvable IfStatement is in ancestors', function () {
|
||||
const consequent = {type: 'BlockStatement'}
|
||||
const ifConsequent = {
|
||||
test: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
},
|
||||
consequent: consequent
|
||||
}
|
||||
const result = filterExecutorsByAncestors(new Set(['browser', 'server']), [
|
||||
{type: 'Program'},
|
||||
{
|
||||
type: 'IfStatement',
|
||||
test: {type: 'Identifier'},
|
||||
consequent: ifConsequent
|
||||
},
|
||||
ifConsequent,
|
||||
consequent
|
||||
])
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
|
||||
})
|
||||
15
tests/lib/util/executors/getExecutors.js
Normal file
15
tests/lib/util/executors/getExecutors.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import getExecutors from '../../../../dist/util/executors/getExecutors'
|
||||
import {UNIVERSAL} from '../../../../dist/util/environment'
|
||||
|
||||
describe('getExecutors', function () {
|
||||
it('returns executors for no ancestors', function () {
|
||||
const result = getExecutors(UNIVERSAL, [])
|
||||
assert.equal(result.size, 3)
|
||||
assert.ok(result.has('browser'))
|
||||
assert.ok(result.has('server'))
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
})
|
||||
80
tests/lib/util/executors/getExecutorsByEnv.js
Normal file
80
tests/lib/util/executors/getExecutorsByEnv.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import getExecutorsByEnv from '../../../../dist/util/executors/getExecutorsByEnv'
|
||||
|
||||
import {
|
||||
PUBLIC,
|
||||
PRIVATE,
|
||||
CLIENT,
|
||||
SERVER,
|
||||
PACKAGE,
|
||||
TEST,
|
||||
NODE_MODULE,
|
||||
UNIVERSAL,
|
||||
PACKAGE_CONFIG,
|
||||
MOBILE_CONFIG,
|
||||
COMPATIBILITY,
|
||||
NON_METEOR
|
||||
} from '../../../../dist/util/environment'
|
||||
|
||||
describe('getExecutorsByEnv', function () {
|
||||
it('public', function () {
|
||||
const result = getExecutorsByEnv(PUBLIC)
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
it('private', function () {
|
||||
const result = getExecutorsByEnv(PRIVATE)
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
it('client', function () {
|
||||
const result = getExecutorsByEnv(CLIENT)
|
||||
assert.equal(result.size, 2)
|
||||
assert.ok(result.has('browser'))
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
it('server', function () {
|
||||
const result = getExecutorsByEnv(SERVER)
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('server'))
|
||||
})
|
||||
it('package', function () {
|
||||
const result = getExecutorsByEnv(PACKAGE)
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
it('test', function () {
|
||||
const result = getExecutorsByEnv(TEST)
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
it('node_module', function () {
|
||||
const result = getExecutorsByEnv(NODE_MODULE)
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
it('universal', function () {
|
||||
const result = getExecutorsByEnv(UNIVERSAL)
|
||||
assert.equal(result.size, 3)
|
||||
assert.ok(result.has('browser'))
|
||||
assert.ok(result.has('server'))
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
it('packageConfig', function () {
|
||||
const result = getExecutorsByEnv(PACKAGE_CONFIG)
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('isobuild'))
|
||||
})
|
||||
it('mobileConfig', function () {
|
||||
const result = getExecutorsByEnv(MOBILE_CONFIG)
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('isobuild'))
|
||||
})
|
||||
it('compatibility', function () {
|
||||
const result = getExecutorsByEnv(COMPATIBILITY)
|
||||
assert.equal(result.size, 2)
|
||||
assert.ok(result.has('cordova'))
|
||||
assert.ok(result.has('browser'))
|
||||
})
|
||||
it('nonMeteor', function () {
|
||||
const result = getExecutorsByEnv(NON_METEOR)
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
})
|
||||
149
tests/lib/util/executors/getExecutorsFromTest.js
Normal file
149
tests/lib/util/executors/getExecutorsFromTest.js
Normal file
@@ -0,0 +1,149 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import getExecutorsFromTest from '../../../../dist/util/executors/getExecutorsFromTest'
|
||||
|
||||
describe('getExecutorsFromTest', function () {
|
||||
describe('MemberExpression', function () {
|
||||
it('isClient', function () {
|
||||
const result = getExecutorsFromTest({
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
})
|
||||
assert.equal(result.size, 2)
|
||||
assert.ok(result.has('browser'))
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
it('isServer', function () {
|
||||
const result = getExecutorsFromTest({
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
})
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('server'))
|
||||
})
|
||||
it('isCordova', function () {
|
||||
const result = getExecutorsFromTest({
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isCordova'
|
||||
}
|
||||
})
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
it('throws on unkown Meteor prop', function () {
|
||||
assert.throws(
|
||||
() => {
|
||||
getExecutorsFromTest({
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isNotAMeteorProp'
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('LogicalExpression', function () {
|
||||
it('resolves isServer AND isClient', function () {
|
||||
const result = getExecutorsFromTest({
|
||||
type: 'LogicalExpression',
|
||||
operator: '&&',
|
||||
left: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
},
|
||||
right: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.equal(result.size, 0)
|
||||
})
|
||||
|
||||
it('resolves isServer OR isClient', function () {
|
||||
const result = getExecutorsFromTest({
|
||||
type: 'LogicalExpression',
|
||||
operator: '||',
|
||||
left: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
},
|
||||
right: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.equal(result.size, 3)
|
||||
assert.ok(result.has('browser'))
|
||||
assert.ok(result.has('server'))
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
|
||||
it('throws for unkown operator in LogicalExpression', function () {
|
||||
assert.throws(() => {
|
||||
getExecutorsFromTest({
|
||||
type: 'LogicalExpression',
|
||||
operator: 'XY',
|
||||
left: {},
|
||||
right: {}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
206
tests/lib/util/executors/isMeteorBlockOnlyTest.js
Normal file
206
tests/lib/util/executors/isMeteorBlockOnlyTest.js
Normal file
@@ -0,0 +1,206 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import isMeteorBlockOnlyTest from '../../../../dist/util/executors/isMeteorBlockOnlyTest'
|
||||
|
||||
describe('isMeteorBlockOnlyTest', function () {
|
||||
|
||||
it('accepts a valid MemberExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
})
|
||||
assert.ok(result)
|
||||
})
|
||||
|
||||
it('accepts a valid computed MemberExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'MemberExpression',
|
||||
computed: true,
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Literal',
|
||||
value: 'isCordova'
|
||||
}
|
||||
})
|
||||
assert.ok(result)
|
||||
})
|
||||
|
||||
it('does not accept an invalid MemberExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Foo'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
})
|
||||
assert.ok(!result)
|
||||
})
|
||||
|
||||
it('accepts a valid UnaryExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'UnaryExpression',
|
||||
operator: '!',
|
||||
argument: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.ok(result)
|
||||
})
|
||||
|
||||
it('does not accept an invalid UnaryExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'UnaryExpression',
|
||||
operator: '!',
|
||||
argument: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Foo'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.ok(!result)
|
||||
})
|
||||
|
||||
it('accepts a valid LogicalExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'LogicalExpression',
|
||||
operator: '||',
|
||||
left: {
|
||||
type: 'LogicalExpression',
|
||||
operator: '&&',
|
||||
left: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
},
|
||||
right: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
}
|
||||
},
|
||||
right: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isCordova'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.ok(result)
|
||||
})
|
||||
|
||||
it('does not accept an invalid LogicalExpression', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'LogicalExpression',
|
||||
operator: '||',
|
||||
left: {
|
||||
type: 'LogicalExpression',
|
||||
operator: '&&',
|
||||
left: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Foo'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
},
|
||||
right: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isServer'
|
||||
}
|
||||
}
|
||||
},
|
||||
right: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Meteor'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isCordova'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.ok(!result)
|
||||
})
|
||||
|
||||
it('returns false for unresolvable expressions', function () {
|
||||
const result = isMeteorBlockOnlyTest({type: 'Identifier'})
|
||||
assert.ok(!result)
|
||||
})
|
||||
|
||||
it('returns false for invalid unary expressions', function () {
|
||||
const result = isMeteorBlockOnlyTest({
|
||||
type: 'UnaryExpression',
|
||||
operator: '-',
|
||||
argument: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
type: 'Identifier',
|
||||
name: 'Foo'
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
name: 'isClient'
|
||||
}
|
||||
}
|
||||
})
|
||||
assert.ok(!result)
|
||||
})
|
||||
|
||||
})
|
||||
39
tests/lib/util/executors/sets.js
Normal file
39
tests/lib/util/executors/sets.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import {difference, union, intersection} from '../../../../dist/util/executors/sets'
|
||||
|
||||
describe('executors', function () {
|
||||
|
||||
describe('union', function () {
|
||||
it('unifies two sets', function () {
|
||||
const result = union(new Set(['cordova']), new Set(['client', 'server']))
|
||||
assert.equal(result.size, 3)
|
||||
assert.ok(result.has('client'))
|
||||
assert.ok(result.has('cordova'))
|
||||
assert.ok(result.has('server'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('difference', function () {
|
||||
it('returns the difference when b contains nothing from a', function () {
|
||||
const result = difference(new Set(['cordova']), new Set(['client', 'server']))
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
|
||||
it('returns the difference when b contains one value from a', function () {
|
||||
const result = difference(new Set(['client', 'cordova']), new Set(['client', 'server']))
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('cordova'))
|
||||
})
|
||||
})
|
||||
|
||||
describe('intersection', function () {
|
||||
it('returns the intersection', function () {
|
||||
const result = intersection(new Set(['client', 'cordova']), new Set(['client', 'server']))
|
||||
assert.equal(result.size, 1)
|
||||
assert.ok(result.has('client'))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -13,7 +13,7 @@ function matcher (filename) {
|
||||
)
|
||||
}
|
||||
|
||||
const findOneUpwards = require('../../../../dist/util/internal/findOneUpwards.js')
|
||||
const findOneUpwards = require('../../../../dist/util/meta/findOneUpwards.js')
|
||||
|
||||
describe('findOneUpwards', function () {
|
||||
it('returns false when no project is found', function () {
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import {NON_METEOR} from '../../../dist/util/environment'
|
||||
import {NON_METEOR} from '../../../../dist/util/environment'
|
||||
|
||||
const rewire = require('rewire')
|
||||
const getMeta = rewire('../../../dist/util/getMeta')
|
||||
const getMeta = rewire('../../../../dist/util/meta/getMeta')
|
||||
getMeta.__set__('getRelativePath', function (path) {
|
||||
return path
|
||||
})
|
||||
@@ -4,7 +4,7 @@ import assert from 'assert'
|
||||
import path from 'path'
|
||||
|
||||
import ENVIRONMENT from '../../../../dist/util/environment.js'
|
||||
import getMeteorMeta from '../../../../dist/util/internal/getMeteorMeta.js'
|
||||
import getMeteorMeta from '../../../../dist/util/meta/getMeteorMeta.js'
|
||||
|
||||
|
||||
describe('getMeteorMeta', function () {
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import assert from 'assert'
|
||||
const rewire = require('rewire')
|
||||
const getRelativePath = rewire('../../../../dist/util/internal/getRelativePath.js')
|
||||
const getRelativePath = rewire('../../../../dist/util/meta/getRelativePath.js')
|
||||
|
||||
getRelativePath.__set__('getRootPath', function (filename) {
|
||||
if (filename === '/Users/anon/git/meteor-project/client/file.js') {
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import assert from 'assert'
|
||||
const rewire = require('rewire')
|
||||
const getRootPath = rewire('../../../../dist/util/internal/getRootPath.js')
|
||||
const getRootPath = rewire('../../../../dist/util/meta/getRootPath.js')
|
||||
|
||||
getRootPath.__set__('findOneUpwards', function (filename) {
|
||||
if (filename === '/Users/anon/git/meteor-project/file.js') {
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import assert from 'assert'
|
||||
const rewire = require('rewire')
|
||||
const isMeteorProject = rewire('../../../../dist/util/internal/isMeteorProject')
|
||||
const isMeteorProject = rewire('../../../../dist/util/meta/isMeteorProject')
|
||||
|
||||
isMeteorProject.__set__('pathExists', {
|
||||
sync: function (path) {
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-env mocha */
|
||||
|
||||
import assert from 'assert'
|
||||
import stripPathPrefix from '../../../../dist/util/internal/stripPathPrefix.js'
|
||||
import stripPathPrefix from '../../../../dist/util/meta/stripPathPrefix.js'
|
||||
|
||||
describe('stripPathPrefix', function () {
|
||||
it('strips path correctly', function () {
|
||||
Reference in New Issue
Block a user