Skip to content

Commit

Permalink
Coverage biashhh, it's working!
Browse files Browse the repository at this point in the history
  • Loading branch information
maticzav committed Aug 28, 2018
1 parent d37648c commit 0cf97de
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .nycrc
Expand Up @@ -3,7 +3,7 @@
"exclude": ["src/**/*.test.ts"],
"extension": [".ts"],
"require": ["ts-node/register"],
"reporter": ["text"],
"reporter": ["text", "html"],
"sourceMap": true,
"instrument": true,
"check-coverage": true,
Expand Down
2 changes: 1 addition & 1 deletion src/constructors.ts
Expand Up @@ -34,7 +34,7 @@ export const rule = (
options?: IRuleConstructorOptions,
) => (func: IRuleFunction): Rule => {
if (typeof name === 'object') {
options = name || {}
options = name
name = Math.random().toString()
} else if (typeof name === 'string') {
options = options || {}
Expand Down
6 changes: 5 additions & 1 deletion src/rules.ts
Expand Up @@ -228,7 +228,11 @@ export class LogicRule implements ILogicRule {
if (isLogicRule(rule)) {
return fragments.concat(...rule.extractFragments())
} else {
return fragments.concat(rule.extractFragment())
if (rule.extractFragment()) {
return fragments.concat(rule.extractFragment())
} else {
return fragments
}
}
}, [])

Expand Down
120 changes: 120 additions & 0 deletions src/test/cache.test.ts
Expand Up @@ -61,6 +61,63 @@ test('Strict cache - Rule is called multiple times, based on different parent.',
})
})

test('Strict cache - Cache is normalised correctly, rule is called multiple times, based on different parent.', async t => {
t.plan(2 + 1)

// Schema
const typeDefs = `
type Query {
test: [Test!]!
}
type Test {
value: String!
}
`
const resolvers = {
Query: {
test: () => [
{ value: 'pass-A' },
{ value: 'pass-A' },
{ value: 'pass-B' },
],
},
}

const schema = makeExecutableSchema({
typeDefs,
resolvers,
})

// Permissions
const allow = rule({ cache: true })(parent => {
t.pass()
return true
})

const permissions = shield({
Test: allow,
})

const schemaWithPermissions = applyMiddleware(schema, permissions)

// Execution
const query = `
query {
test {
value
}
}
`
const res = await graphql(schemaWithPermissions, query, undefined, {})

t.deepEqual(res, {
data: {
test: [{ value: 'pass-A' }, { value: 'pass-A' }, { value: 'pass-B' }],
},
})
})

test('Strict cache - Rule is called multiple times, based on different arguments.', async t => {
t.plan(3 + 1)

Expand Down Expand Up @@ -260,3 +317,66 @@ test('No Cache - rule is reexecuted every time.', async t => {
},
})
})

test('No Cache - Cache is normalised correctly, rule is reexecuted every time.', async t => {
t.plan(5 + 1)

// Schema
const typeDefs = `
type Query {
a: String!
b: String!
c(arg: String): String!
d(arg: String): String!
e(arg: String): String!
}
`
const resolvers = {
Query: {
a: () => 'a',
b: () => 'b',
c: () => 'c',
d: () => 'd',
e: () => 'e',
},
}

const schema = makeExecutableSchema({
typeDefs,
resolvers,
})

// Permissions
const allow = rule({ cache: false })(parent => {
t.pass()
return true
})

const permissions = shield({
Query: allow,
})

const schemaWithPermissions = applyMiddleware(schema, permissions)

// Execution
const query = `
query {
a
b
c(arg: "foo")
d(arg: "bar")
e
}
`
const res = await graphql(schemaWithPermissions, query, undefined, {})

t.deepEqual(res, {
data: {
a: 'a',
b: 'b',
c: 'c',
d: 'd',
e: 'e',
},
})
})
62 changes: 55 additions & 7 deletions src/test/error.test.ts
Expand Up @@ -4,7 +4,7 @@ import { applyMiddleware } from 'graphql-middleware'
import { makeExecutableSchema } from 'graphql-tools'
import { shield, rule, allow } from '../index'

test('Error in resolver, fallback.', async t => {
test('Error in resolver resolves in fallback.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -52,7 +52,7 @@ test('Error in resolver, fallback.', async t => {
t.is(res.errors[0].message, fallback.message)
})

test('Error in rule, fallback.', async t => {
test('Error in rule resolves in fallback.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -102,7 +102,7 @@ test('Error in rule, fallback.', async t => {
t.is(res.errors[0].message, fallback.message)
})

test('Error in resolver, allow external errors.', async t => {
test('Error in resolver with allowed external errors resolves in external error.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -146,7 +146,7 @@ test('Error in resolver, allow external errors.', async t => {
t.is(res.errors[0].message, 'external')
})

test('Error in rule with allow external errors, returns fallback.', async t => {
test('Error in rule with allowed external errors returns fallback.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -192,7 +192,7 @@ test('Error in rule with allow external errors, returns fallback.', async t => {
t.is(res.errors[0].message, 'Not Authorised!')
})

test('Custom error in rule.', async t => {
test('Custom error in rule resolves in custom error.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -235,7 +235,7 @@ test('Custom error in rule.', async t => {
t.is(res.errors[0].message, error.message)
})

test('Return original error in debug mode, rule.', async t => {
test('Return original error in debug mode when error occurs in rule.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -281,7 +281,7 @@ test('Return original error in debug mode, rule.', async t => {
t.is(res.errors[0].message, 'debug')
})

test('Return original error in debug mode, resolver.', async t => {
test('Return original error in debug mode when error occurs in resolver.', async t => {
// Schema
const typeDefs = `
type Query {
Expand Down Expand Up @@ -328,3 +328,51 @@ test('Return original error in debug mode, resolver.', async t => {
t.is(res.data, null)
t.is(res.errors[0].message, 'debug')
})

test('Correctly converts string fallback to error fallback.', async t => {
// Schema
const typeDefs = `
type Query {
test: String!
}
`
const resolvers = {
Query: {
test: () => {
throw new Error()
},
},
}

const schema = makeExecutableSchema({
typeDefs,
resolvers,
})

// Fallback

const fallbackMessage = 'fallback'

// Permissions
const permissions = shield(
{
Query: allow,
},
{
fallback: fallbackMessage,
},
)

const schemaWithPermissions = applyMiddleware(schema, permissions)

// Execution
const query = `
query {
test
}
`
const res = await graphql(schemaWithPermissions, query)

t.is(res.data, null)
t.is(res.errors[0].message, fallbackMessage)
})
7 changes: 6 additions & 1 deletion src/test/fragments.test.ts
Expand Up @@ -8,11 +8,16 @@ test('Extracts fragment from rule correctly.', async t => {
})

test('Extracts fragment from logic rule correctly.', async t => {
const ruleWithNoFragment = rule()(() => true)
const ruleWithFragmentA = rule({ fragment: 'pass-A' })(() => true)
const ruleWithFragmentB = rule({ fragment: 'pass-B' })(() => true)
const ruleWithFragmentC = rule({ fragment: 'pass-C' })(() => true)

const logicRuleAND = and(ruleWithFragmentA, ruleWithFragmentB)
const logicRuleAND = and(
ruleWithNoFragment,
ruleWithFragmentA,
ruleWithFragmentB,
)
const logicRuleNOT = not(logicRuleAND)
const logicRuleOR = or(ruleWithFragmentB, ruleWithFragmentC, logicRuleNOT)

Expand Down
51 changes: 50 additions & 1 deletion src/test/generator.test.ts
@@ -1,8 +1,9 @@
import test from 'ava'
import { graphql } from 'graphql'
import { applyMiddleware } from 'graphql-middleware'
import { applyMiddleware, middleware } from 'graphql-middleware'
import { makeExecutableSchema } from 'graphql-tools'
import { shield, rule, allow, deny } from '../'
import { generateMiddlewareGeneratorFromRuleTree } from '../generator'

test('Generator - whitelist permissions.', async t => {
// Schema
Expand Down Expand Up @@ -213,3 +214,51 @@ test('Generator - apply fragments in generated middleware correctly.', async t =
},
])
})

test('Generator generates schema wide middleware correctly.', async t => {
// Schema
const typeDefs = `
type Query {
test: String
type: Test
}
type Test {
typeTest: String
}
`
const resolvers = {
Query: {
test: () => 'pass',
},
Test: {
typeTest: () => 'pass',
},
}

const schema = makeExecutableSchema({
typeDefs,
resolvers,
})

const permissions = shield(deny)

const schemaWithPermissions = applyMiddleware(schema, permissions)

// Execution
const query = `
query {
test
type {
typeTest
}
}
`
const res = await graphql(schemaWithPermissions, query)

t.deepEqual(res.data, {
test: null,
type: null,
})
t.not(res.errors.length, 0)
})

0 comments on commit 0cf97de

Please sign in to comment.