diff --git a/src/__tests__/__snapshots__/integration-test.ts.snap b/src/__tests__/__snapshots__/integration-test.ts.snap index 1d766599..c5a2444b 100644 --- a/src/__tests__/__snapshots__/integration-test.ts.snap +++ b/src/__tests__/__snapshots__/integration-test.ts.snap @@ -1,315 +1,73 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`integration with apollo-server correct span nesting 1`] = ` -Object { - "children": Array [ - Object { - "children": Array [ - Object { - "children": Array [], - "finished": true, - "id": 6, - "logs": Array [ - Object { - "result": "\\"1\\"", - }, - ], - "name": "one", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 5, - "log": [Function], - "name": "a", - }, - }, - "parentId": 5, - }, - Object { - "children": Array [], - "finished": true, - "id": 7, - "logs": Array [ - Object { - "result": "\\"2\\"", - }, - ], - "name": "two", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 5, - "log": [Function], - "name": "a", - }, - }, - "parentId": 5, - }, - ], - "finished": true, - "id": 5, - "logs": Array [ - Object { - "result": "{\\"one\\":\\"1\\",\\"two\\":\\"2\\",\\"three\\":[{\\"four\\":\\"4\\"},{\\"four\\":\\"IV\\"}]}", - }, - ], - "name": "a", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 4, - "log": [Function], - "name": "request", - }, - }, - "parentId": 4, - }, - ], - "finished": true, - "id": 4, - "logs": Array [ - Object { - "queryString": "query { - a { - one - two - } - }", - }, - ], - "name": "request", - "options": Object { - "childOf": undefined, - }, - "parentId": undefined, -} +request:1 + finished: true + logs: + 1. {"queryString":"query {\\n a {\\n one\\n two\\n }\\n }"} ++-- a:2 + finished: true + logs: + 1. {"result":"{one:1,two:2,three:[{four:4},{four:IV}]}"} + +-- one:3 + finished: true + logs: + 1. {"result":"1"} + +-- two:4 + finished: true + logs: + 1. {"result":"2"} + `; exports[`integration with apollo-server does not start a field resolver span if the parent field resolver was not traced 1`] = ` -Object { - "children": Array [ - Object { - "children": Array [ - Object { - "children": Array [], - "finished": true, - "id": 10, - "logs": Array [ - Object { - "result": "\\"4\\"", - }, - ], - "name": "four", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 9, - "log": [Function], - "name": "b", - }, - }, - "parentId": 9, - }, - ], - "finished": true, - "id": 9, - "logs": Array [ - Object { - "result": "{\\"four\\":\\"4\\"}", - }, - ], - "name": "b", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 8, - "log": [Function], - "name": "request", - }, - }, - "parentId": 8, - }, - ], - "finished": true, - "id": 8, - "logs": Array [ - Object { - "queryString": "query { - a { - one - two - } - b { - four - } - }", - }, - ], - "name": "request", - "options": Object { - "childOf": undefined, - }, - "parentId": undefined, -} +request:1 + finished: true + logs: + 1. {"queryString":"query {\\n a {\\n one\\n two\\n }\\n b {\\n four\\n }\\n }"} ++-- b:2 + finished: true + logs: + 1. {"result":"{four:4}"} + +-- four:3 + finished: true + logs: + 1. {"result":"4"} + `; exports[`integration with apollo-server implements traces for arrays 1`] = ` -Object { - "children": Array [ - Object { - "children": Array [ - Object { - "children": Array [], - "finished": true, - "id": 13, - "logs": Array [ - Object { - "result": "\\"1\\"", - }, - Object { - "result": "\\"I\\"", - }, - Object { - "result": "\\"eins\\"", - }, - ], - "name": "one", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 12, - "log": [Function], - "name": "as", - }, - }, - "parentId": 12, - }, - Object { - "children": Array [], - "finished": true, - "id": 14, - "logs": Array [ - Object { - "result": "\\"2\\"", - }, - Object { - "result": "\\"II\\"", - }, - Object { - "result": "\\"zwei\\"", - }, - ], - "name": "two", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 12, - "log": [Function], - "name": "as", - }, - }, - "parentId": 12, - }, - Object { - "children": Array [], - "finished": false, - "id": 15, - "logs": Array [], - "name": "one", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 12, - "log": [Function], - "name": "as", - }, - }, - "parentId": 12, - }, - Object { - "children": Array [], - "finished": false, - "id": 16, - "logs": Array [], - "name": "two", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 12, - "log": [Function], - "name": "as", - }, - }, - "parentId": 12, - }, - Object { - "children": Array [], - "finished": false, - "id": 17, - "logs": Array [], - "name": "one", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 12, - "log": [Function], - "name": "as", - }, - }, - "parentId": 12, - }, - Object { - "children": Array [], - "finished": false, - "id": 18, - "logs": Array [], - "name": "two", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 12, - "log": [Function], - "name": "as", - }, - }, - "parentId": 12, - }, - ], - "finished": true, - "id": 12, - "logs": Array [ - Object { - "result": "[{\\"one\\":\\"1\\",\\"two\\":\\"2\\"},{\\"one\\":\\"I\\",\\"two\\":\\"II\\"},{\\"one\\":\\"eins\\",\\"two\\":\\"zwei\\"}]", - }, - ], - "name": "as", - "options": Object { - "childOf": Object { - "finish": [Function], - "id": 11, - "log": [Function], - "name": "request", - }, - }, - "parentId": 11, - }, - ], - "finished": true, - "id": 11, - "logs": Array [ - Object { - "queryString": "query { - as { - one - two - } - }", - }, - ], - "name": "request", - "options": Object { - "childOf": undefined, - }, - "parentId": undefined, -} +request:1 + finished: true + logs: + 1. {"queryString":"query {\\n as {\\n one\\n two\\n }\\n }"} ++-- as:2 + finished: true + logs: + 1. {"result":"[{one:1,two:2},{one:I,two:II},{one:eins,two:zwei}]"} + +-- one:3 + finished: true + logs: + 1. {"result":"1"} + +-- two:4 + finished: true + logs: + 1. {"result":"2"} + +-- one:5 + finished: true + logs: + 1. {"result":"I"} + +-- two:6 + finished: true + logs: + 1. {"result":"II"} + +-- one:7 + finished: true + logs: + 1. {"result":"eins"} + +-- two:8 + finished: true + logs: + 1. {"result":"zwei"} + `; diff --git a/src/__tests__/integration-test.ts b/src/__tests__/integration-test.ts index 9a6ae8ef..69a16143 100644 --- a/src/__tests__/integration-test.ts +++ b/src/__tests__/integration-test.ts @@ -2,21 +2,17 @@ import * as express from "express"; import * as request from "supertest"; import { ApolloServer } from "apollo-server-express"; import ApolloOpentracing from "../"; +import spanSerializer from "../test/span-serializer"; +import { MockSpan, MockSpanTree } from "../test/types"; -let mockSpanId = 1; +expect.addSnapshotSerializer(spanSerializer); -interface MockSpan { - id: number; - parentId?: number; - name: string; - options?: any; - logs: any[]; - finished: boolean; -} +let mockSpanId = 1; -interface MockSpanTree extends MockSpan { - children: MockSpanTree[]; -} +// Stable spanId's +beforeEach(() => { + mockSpanId = 1; +}); const buildSpanTree = (spans: MockSpan[]) => { // TODO we currently assume there is only one null parent entry. @@ -102,7 +98,7 @@ class MockTracer { return { log(object) { - self.spans.find(span => span.name === name).logs.push(object); + self.spans.find(span => span.id === spanId).logs.push(object); }, id: spanId, @@ -110,7 +106,7 @@ class MockTracer { name: name, finish() { - self.spans.find(span => span.name === name).finished = true; + self.spans.find(span => span.id === spanId).finished = true; } }; } diff --git a/src/test/span-serializer.ts b/src/test/span-serializer.ts new file mode 100644 index 00000000..7424edae --- /dev/null +++ b/src/test/span-serializer.ts @@ -0,0 +1,58 @@ +import "jest"; +import { MockSpanTree } from "./types"; + +const TAB = " "; + +function prefix(depth: number) { + return TAB.repeat(depth) + `+-- `; +} + +function logLine(log: any, index: number, depth: number) { + return `${TAB.repeat(depth + 1)}${index}. ${JSON.stringify(log).replace( + /\\"/g, + "" + )}`; +} + +function logs(span: MockSpanTree, depth: number) { + if (span.logs && span.logs.length > 0) { + return `${TAB.repeat(depth + 1)}logs:\n${span.logs + .map((log, index) => logLine(log, index + 1, depth)) + .join("\n")}\n`; + } + + return ""; +} + +function tag(span: MockSpanTree, depth: number) { + return `${span.name}:${span.id}\n${TAB.repeat(depth + 1)}finished: ${ + span.finished + }\n${logs(span, depth)}`; +} + +function buildSpan(span: MockSpanTree, depth = 0) { + let result = ""; + + result += tag(span, depth); + + if (span.children) { + for (const child of span.children) { + result += `${prefix(depth)}${buildSpan(child, depth + 1)}`; + } + } + + return result; +} + +export default { + test: (val: any) => val.id && val.name && val.logs && val.finished != null, + print( + val: any, + _serialize: ((val: any) => string), + _indent: ((str: string) => string), + _opts: jest.SnapshotSerializerOptions, + _colors: jest.SnapshotSerializerColors + ) { + return buildSpan(val as MockSpanTree); + } +}; diff --git a/src/test/types.ts b/src/test/types.ts new file mode 100644 index 00000000..cd4ebc96 --- /dev/null +++ b/src/test/types.ts @@ -0,0 +1,12 @@ +export interface MockSpan { + id: number; + parentId?: number; + name: string; + options?: any; + logs: any[]; + finished: boolean; +} + +export interface MockSpanTree extends MockSpan { + children: MockSpanTree[]; +}