From 6b5d329759fc6958a05311796fda02decb3a5cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Fri, 15 Feb 2019 01:46:33 +0100 Subject: [PATCH] Implement test for search @appinteractive could you have a look if sanitization of search queries work? I created a test and I see "unterminated string" exceptions. This is not what we want! All user input should be escaped. --- src/schema.graphql | 3 +-- src/schema.graphql.spec.js | 18 +++++++++++++++--- src/seed/factories/index.js | 3 ++- src/seed/factories/posts.js | 22 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/seed/factories/posts.js diff --git a/src/schema.graphql b/src/schema.graphql index 472b345d7..ee519fff3 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -3,8 +3,7 @@ type Query { statistics: Statistics! findPosts(filter: String!, limit: Int = 10): [Post]! @cypher( statement: """ - CALL db.index.fulltext.queryNodes( - 'full_text_search', $filter+'~') + CALL db.index.fulltext.queryNodes('full_text_search', $filter+'~') YIELD node AS node RETURN node ORDER BY node.createdAt DESC diff --git a/src/schema.graphql.spec.js b/src/schema.graphql.spec.js index 304fdf557..5fdc67d0c 100644 --- a/src/schema.graphql.spec.js +++ b/src/schema.graphql.spec.js @@ -21,7 +21,7 @@ describe('filter for searchQuery', () => { }) await create('post', { title: 'Threepenny Opera', - content: 'And the shark, it has teeth, And it wears them in the face.' + content: 'And the shark, it has teeth, And it wears them in the face.' }) }) @@ -29,6 +29,18 @@ describe('filter for searchQuery', () => { await cleanDatabase() }) + describe('sanitization', () => { + it('escapes cypher statement', async () => { + await request(host, query(`''); + MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r; + CALL db.index.fulltext.queryNodes('full_text_search', '' + `)) + console.log(data) + const data = await request(host, query('the')) + expect(data).toEqual({findPosts: [{title: 'Hamlet'}, {title: 'Threepenny Opera'}]}) + }) + }) + describe('result set', () => { describe('includes posts if search term', () => { it('matches title', async () => { @@ -36,8 +48,8 @@ describe('filter for searchQuery', () => { expect(data).toEqual({findPosts: [{title: 'Hamlet'}]}) }) - it('matches a part of the title', async () => { - const data = await request(host, query('let')) + it('matches mistyped title', async () => { + const data = await request(host, query('amlet')) expect(data).toEqual({findPosts: [{title: 'Hamlet'}]}) }) diff --git a/src/seed/factories/index.js b/src/seed/factories/index.js index e62e98869..9c6d4116c 100644 --- a/src/seed/factories/index.js +++ b/src/seed/factories/index.js @@ -20,7 +20,8 @@ const client = new ApolloClient({ const driver = neo4j().getDriver() const builders = { - 'user': require('./users.js').default + 'user': require('./users.js').default, + 'post': require('./posts.js').default } const buildMutation = (model, parameters) => { diff --git a/src/seed/factories/posts.js b/src/seed/factories/posts.js new file mode 100644 index 000000000..366b64155 --- /dev/null +++ b/src/seed/factories/posts.js @@ -0,0 +1,22 @@ +import faker from 'faker' + +export default function (params) { + const { + id = Array.from({length: 3}, () => faker.lorem.word()).join(''), + title = faker.lorem.sentence(), + content = Array.from({length: 10}, () => faker.lorem.sentence()).join(' ') + } = params + return ` + mutation { + ${id}: CreatePost( + id: "${id}", + title: "${title}", + content: "${content}", + image: "https://picsum.photos/1280/1024?image=424", + visibility: public, + disabled: false, + deleted: false + ) { title } + } + ` +}