Last active
August 20, 2020 22:39
-
-
Save alexbeletsky/248b2072f8d6bd33ea2705a9aac5900c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-console */ | |
/* eslint-disable prefer-arrow-callback */ | |
import expect from 'expect'; | |
import { createTestClient } from 'apollo-server-testing'; | |
import ggl from 'graphql-tag'; | |
import config from '../../../config'; | |
import { createServer } from '../../../src/server'; | |
import { createTestApiServer } from '../../utils'; | |
import { fixtures } from './fixtures'; | |
describe('[queries] channel search queries', function () { | |
before('create graphql server', async function () { | |
const { apollo, server } = await createServer(); | |
this.apollo = apollo; | |
this.server = server; | |
this.client = createTestClient(this.apollo); | |
}); | |
before('create api server', async function () { | |
const { server } = await createTestApiServer(config.aurum); | |
this.apiServer = server; | |
}); | |
after('stop server', async function () { | |
await this.server.close(); | |
await this.apiServer.close(); | |
}); | |
describe('with channel insights field', function () { | |
before('reset api calls', function () { | |
this.apiServer.reset(); | |
}); | |
before('setup aurum calls', function () { | |
this.apiServer.mockResponse({ | |
method: 'GET', | |
url: '/v2/channels/search', | |
response: { | |
statusCode: 200, | |
data: fixtures.aurum.instagram, | |
}, | |
}); | |
}); | |
before('execute query', async function () { | |
const { | |
client: { query }, | |
} = this; | |
const QUERY = ggl` | |
query channelSearch( | |
$page: Int = 1, | |
$query: ChannelSearchQuery, | |
$sort: ChannelSearchSort | |
) { | |
channelSearch(page: $page, query: $query, sort: $sort) { | |
data { | |
id | |
insights { | |
... on PlatformInsights { | |
followedBy | |
follows | |
media | |
} | |
} | |
} | |
} | |
} | |
`; | |
this.response = await query({ | |
query: QUERY, | |
variables: { | |
query: { platforms: ['platform'] }, | |
sort: { createdAt: -1 }, | |
}, | |
}); | |
}); | |
it('should not have errors', function () { | |
expect(this.response.errors).toNotExist(); | |
}); | |
it('should have correct api requests', function () { | |
expect(this.aurumServer.requests()).toMatchSnapshot(this); | |
}); | |
it('should have correct response', function () { | |
expect(this.response).toMatchSnapshot(this); | |
}); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// inspired by James Shore Spy-Server | |
// https://www.jamesshore.com/v2/blog/2018/testing-without-mocks#spy-server | |
import _ from 'lodash'; | |
import Http from 'http'; | |
import { promisify } from 'util'; | |
export class ApiTestServer { | |
constructor(options = {}) { | |
const { url } = options; | |
if (!url) { | |
throw new Error('missing url parameter'); | |
} | |
this.url = new URL('/', url); | |
this.router = new Router(); | |
this.reset(); | |
} | |
reset() { | |
this.router.reset(); | |
} | |
hostname() { | |
return this.url.hostname; | |
} | |
port() { | |
return this.url.port; | |
} | |
host() { | |
return this.url.host; | |
} | |
async start() { | |
this.server = Http.createServer(); | |
this.server.on('request', ApiTestServer.handleRequest.bind(null, this)); | |
await promisify(this.server.listen.bind(this.server))( | |
this.port(), | |
this.hostname(), | |
); | |
} | |
async close() { | |
await promisify(this.server.close.bind(this.server))(); | |
} | |
mockResponse(response) { | |
this.router.setResponse(response); | |
} | |
requests() { | |
return this.router.requests; | |
} | |
static handleRequest(self, request, response) { | |
self.router.route(request, response); | |
} | |
} | |
class Router { | |
constructor() { | |
this.defaultResponse = { statusCode: 200, data: {} }; | |
this.reset(); | |
} | |
reset() { | |
this.routes = {}; | |
this.requests = []; | |
} | |
setResponse({ method, url, response }) { | |
if (!method) { | |
throw new Error('missing method parameter'); | |
} | |
if (!url) { | |
throw new Error('missing url parameter'); | |
} | |
if (!response) { | |
throw new Error('missing response parameter'); | |
} | |
if (!response.statusCode || !response.data) { | |
throw new Error('response is missing statusCode or data'); | |
} | |
const routeKey = Router.routeKey(method, url); | |
const route = this.routes[routeKey]; | |
this.routes[routeKey] = route || []; | |
this.routes[routeKey].push(response); | |
} | |
route(request, response) { | |
const { method, url } = request; | |
const { pathname, searchParams } = new URL(url, 'http://test.server'); | |
const { statusCode, data, skipped } = this.responseFromRoute( | |
method, | |
pathname, | |
); | |
const requestLog = { | |
request: { | |
method, | |
url: pathname, | |
params: searchParams, | |
headers: _.omit(request.headers, 'connection'), | |
body: '', | |
}, | |
response: { | |
statusCode, | |
data, | |
skipped, | |
}, | |
}; | |
request.on('data', (data) => { | |
requestLog.request.body += data; | |
}); | |
this.requests.push(requestLog); | |
return Router.endRequest(request, response, { | |
statusCode, | |
data, | |
}); | |
} | |
responseFromRoute(method, url) { | |
const responses = this.routes[Router.routeKey(method, url)]; | |
if (!responses || !responses.length) { | |
return { | |
...this.defaultResponse, | |
skipped: | |
'This request is NOT mocked and responded with default response', | |
}; | |
} | |
return { ...responses.shift(), skipped: false }; | |
} | |
static routeKey(method, url) { | |
return `${method}.${url}`; | |
} | |
static endRequest(request, response, { statusCode, data }) { | |
request.on('end', () => { | |
response.statusCode = statusCode; | |
response.end(JSON.stringify(data)); | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Jest Snapshot v1, https://goo.gl/fbAQLP | |
exports[`[queries] channel search queries with channel insights field for instagram should have correct api requests 1`] = ` | |
Array [ | |
Object { | |
"request": Object { | |
"body": "{\\"token\\":\\"authToken\\"}", | |
"headers": Object { | |
"accept": "application/json", | |
"content-length": "21", | |
"content-type": "application/json", | |
"host": "localhost:8084", | |
}, | |
"method": "POST", | |
"params": URLSearchParams { | |
Symbol(query): Array [], | |
Symbol(context): "http://test.server/v1/auth/token", | |
}, | |
"url": "/v1/auth/token", | |
}, | |
"response": Object { | |
"data": Object {}, | |
"skipped": "This request is NOT mocked and responded with default response", | |
"statusCode": 200, | |
}, | |
}, | |
Object { | |
"request": Object { | |
"body": "", | |
"headers": Object { | |
"accept": "application/json", | |
"host": "localhost:8084", | |
}, | |
"method": "GET", | |
"params": URLSearchParams { | |
Symbol(query): Array [ | |
"page", | |
"1", | |
"query", | |
"{\\"platforms\\":[\\"instagram\\"],\\"hideForExternals\\":false}", | |
"sort", | |
"{\\"createdAt\\":-1}", | |
"fields", | |
"[\\"id\\",\\"user\\",\\"name\\",\\"platform\\",\\"reach\\",\\"categories\\",\\"data\\",\\"kpi\\",\\"external\\"]", | |
], | |
Symbol(context): "http://test.server/v2/channels/search?page=1&query=%7B%22platforms%22%3A%5B%22instagram%22%5D%2C%22hideForExternals%22%3Afalse%7D&sort=%7B%22createdAt%22%3A-1%7D&fields=%5B%22id%22%2C%22user%22%2C%22name%22%2C%22platform%22%2C%22reach%22%2C%22categories%22%2C%22data%22%2C%22kpi%22%2C%22external%22%5D", | |
}, | |
"url": "/v2/channels/search", | |
}, | |
"response": Object { | |
"data": Object { | |
"data": Array [ | |
Object { | |
"categories": Array [], | |
"data": Object { | |
"url": "https://instagram.com/oneofthebest", | |
}, | |
"external": false, | |
"id": "000000000000000000000001", | |
"insights": Object { | |
"date": 2020-08-20T20:06:24.522Z, | |
"followedBy": 10, | |
"follows": 1000, | |
"media": 111, | |
}, | |
"kpi": Object {}, | |
"name": "oneofthebest", | |
"platform": "instagram", | |
"reach": 10000, | |
"user": Object { | |
"firstname": "dude", | |
"id": 1, | |
}, | |
}, | |
Object { | |
"categories": Array [], | |
"data": Object { | |
"url": "https://instagram.com/not", | |
}, | |
"external": false, | |
"id": "000000000000000000000002", | |
"insights": Object { | |
"date": 2020-08-20T20:06:24.522Z, | |
"followedBy": 1000, | |
"follows": 1, | |
"media": 500, | |
}, | |
"kpi": Object {}, | |
"name": "not", | |
"platform": "instagram", | |
"reach": 8999, | |
"user": Object { | |
"firstname": "ahh", | |
"id": 1, | |
}, | |
}, | |
Object { | |
"categories": Array [], | |
"data": Object { | |
"url": "https://instagram.com/billie", | |
}, | |
"external": false, | |
"id": "000000000000000000000003", | |
"insights": Object {}, | |
"kpi": Object {}, | |
"name": "billie", | |
"platform": "instagram", | |
"reach": 0, | |
"user": Object { | |
"firstname": "billie", | |
"id": 1, | |
}, | |
}, | |
], | |
"meta": Object {}, | |
}, | |
"skipped": false, | |
"statusCode": 200, | |
}, | |
}, | |
] | |
`; | |
exports[`[queries] channel search queries with channel insights field for instagram should have correct response 1`] = ` | |
Object { | |
"data": Object { | |
"channelSearch": Object { | |
"data": Array [ | |
Object { | |
"id": "000000000000000000000001", | |
"insights": Object { | |
"followedBy": 10, | |
"follows": 1000, | |
"media": 111, | |
}, | |
}, | |
Object { | |
"id": "000000000000000000000002", | |
"insights": Object { | |
"followedBy": 1000, | |
"follows": 1, | |
"media": 500, | |
}, | |
}, | |
Object { | |
"id": "000000000000000000000003", | |
"insights": Object {}, | |
}, | |
], | |
}, | |
}, | |
"errors": undefined, | |
"extensions": undefined, | |
"http": Object { | |
"headers": Headers { | |
Symbol(map): Object {}, | |
}, | |
}, | |
} | |
`; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment