Skip to content

Commit

Permalink
feat(graphql): add basic GraphQL wrapper function
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Apr 22, 2018
1 parent 688c035 commit 641e0e7
Show file tree
Hide file tree
Showing 18 changed files with 322 additions and 247 deletions.
2 changes: 1 addition & 1 deletion examples/e2e/test/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const opts = {
pactBrokerUsername: 'dXfltyFMgNOFZAxr8io9wJ37iUpY42M',
pactBrokerPassword: 'O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1',
tags: ['prod', 'test'],
consumerVersion: '1.0.1'
consumerVersion: '1.0.' + ((process.env.TRAVIS_BUILD_NUMBER) ? process.env.TRAVIS_BUILD_NUMBER : Math.floor(new Date() / 1000))
}

pact.publishPacts(opts)
Expand Down
35 changes: 0 additions & 35 deletions examples/graphql/consumer.js

This file was deleted.

60 changes: 0 additions & 60 deletions examples/graphql/consumer.spec.js

This file was deleted.

61 changes: 61 additions & 0 deletions examples/graphql/consumer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// POC that graphQL endpoints can be tested!
/* tslint:disable:no-unused-expression object-literal-sort-keys max-classes-per-file no-empty */

import * as chai from "chai";
import * as chaiAsPromised from "chai-as-promised";
import * as sinon from "sinon";
import { like, term } from "../../src/dsl/matchers";
import { query } from "./consumer";
import { Pact, GraphQLInteraction } from "../../src/pact";

const path = require("path");
const expect = chai.expect;

chai.use(chaiAsPromised);

describe("GraphQL example", () => {
const provider = new Pact({
port: 4000,
log: path.resolve(process.cwd(), "logs", "mockserver-integration.log"),
dir: path.resolve(process.cwd(), "pacts"),
consumer: "GraphQLConsumer",
provider: "GraphQLProvider",
});

before(() => provider.setup());
after(() => provider.finalize());

describe("query hello on /graphql", () => {
before(() => {
const graphqlQuery = new GraphQLInteraction()
.uponReceiving("a hello request")
.withQuery(`{ hello }`)
.withRequest({
path: "/graphql",
method: "POST",
})
.withVariables({
foo: "bar",
})
.willRespondWith({
status: 200,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
body: {
data: {
hello: like("Hello world!"),
},
},
});
return provider.addInteraction(graphqlQuery);
});

it("returns the correct response", (done) => {
expect(query()).to.eventually.deep.eq({ hello: "Hello world!" }).notify(done);
});

// verify with Pact, and reset expectations
afterEach(() => provider.verify());
});
});
30 changes: 30 additions & 0 deletions examples/graphql/consumer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ApolloClient, HttpLink } from "apollo-boost";
import { InMemoryCache } from "apollo-cache-inmemory";
import gql from "graphql-tag";
import { createHttpLink } from "apollo-link-http";

const client = new ApolloClient({
cache: new InMemoryCache(),
link: createHttpLink({
fetch: require("node-fetch"),
headers: {
foo: "bar",
},
uri: "http://localhost:4000/graphql",
}),
});

export function query(): any {
return client
.query({
query: gql`
{
hello
}
`,
variables: {
foo: "bar",
},
})
.then((result: any) => result.data);
}
1 change: 1 addition & 0 deletions examples/graphql/foo.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 12 additions & 5 deletions examples/graphql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
"description": "",
"main": "index.js",
"scripts": {
"test:consumer": "mocha consumer.spec.js",
"test:provider": "mocha provider.spec.js"
"build": "tsc",
"clean": "if [ -d 'pacts' ]; then rm -rf pacts; fi",
"test": "npm run clean && npm run test:consumer && npm run test:publish && npm run test:provider",
"test:consumer": "nyc --check-coverage --reporter=html --reporter=text-summary mocha consumer.spec.ts",
"test:publish": "node publish.js",
"test:provider": "nyc --check-coverage --reporter=html --reporter=text-summary mocha -t 10000 provider.spec.ts"
},
"keywords": [
"graphql",
Expand All @@ -15,20 +19,23 @@
"author": "Matt Fellows <matt.fellows@onegeek.com.au>",
"license": "ISC",
"dependencies": {
"@types/chai-as-promised": "^7.1.0",
"apollo-boost": "^0.1.4",
"apollo-client": "^2.2.8",
"apollo-client-preset": "^1.0.8",
"apollo-server-express": "^1.3.5",
"body-parser": "^1.18.2",
"chai-as-promised": "^7.1.1",
"express": "^4.16.3",
"express-graphql": "^0.6.12",
"graphql": "^0.13.2",
"graphql-tag": "^2.9.1",
"graphql-tools": "^2.24.0",
"react-apollo": "^2.1.3"
"graphql-tools": "^2.24.0"
},
"devDependencies": {
"@types/mocha": "^2.2.41",
"chai": "^4.1.2",
"mocha": "^5.1.1"
"mocha": "^5.1.1",
"nyc": "^11.6.0"
}
}
29 changes: 0 additions & 29 deletions examples/graphql/provider.js

This file was deleted.

32 changes: 0 additions & 32 deletions examples/graphql/provider.spec.js

This file was deleted.

37 changes: 37 additions & 0 deletions examples/graphql/provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Verifier } from "../../src/pact";
import * as chai from "chai";
import * as chaiAsPromised from "chai-as-promised";

import { VerifierOptions } from "@pact-foundation/pact-node";
import app from "./provider";

const expect = chai.expect;
const path = require("path");
chai.use(chaiAsPromised);

const server = app.listen(4000, () => console.log("Now browse to localhost:4000/graphql"));

// Verify that the provider meets all consumer expectations
describe("Pact Verification", () => {
it("should validate the expectations of Matching Service", () => { // lexical binding required here
const opts = {
provider: "GraphQLProvider",
providerBaseUrl: "http://localhost:4000/graphql",
// Local pacts
// pactUrls: [path.resolve(process.cwd(), "./pacts/graphqlconsumer-graphqlprovider.json")],
pactBrokerUrl: "https://test.pact.dius.com.au/",
pactBrokerUsername: "dXfltyFMgNOFZAxr8io9wJ37iUpY42M",
pactBrokerPassword: "O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1",
publishVerificationResult: true,
providerVersion: "1.0.0",
tags: ["prod"],
};

return new Verifier().verifyProvider(opts)
.then((output) => {
console.log("Pact Verification Complete!");
console.log(output);
server.close();
});
});
});
26 changes: 26 additions & 0 deletions examples/graphql/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const express = require("express");
const graphqlHTTP = require("express-graphql");
const { buildSchema } = require("graphql");

const schema = buildSchema(`
type Query {
hello: String
}
`);

const root = {
hello: () => "Hello world!",
};

const app = express();
export default app;

app.use("/graphql", graphqlHTTP({
graphiql: true,
rootValue: root,
schema,
}));

export function start(): any {
app.listen(4000, () => console.log("Now browse to localhost:4000/graphql"));
}
23 changes: 23 additions & 0 deletions examples/graphql/publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const pact = require('@pact-foundation/pact-node')
const path = require('path')
const opts = {
pactFilesOrDirs: [path.resolve(__dirname, 'pacts/graphqlconsumer-graphqlprovider.json')],
pactBroker: 'https://test.pact.dius.com.au',
pactBrokerUsername: 'dXfltyFMgNOFZAxr8io9wJ37iUpY42M',
pactBrokerPassword: 'O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1',
tags: ['prod', 'test'],
consumerVersion: '1.0.' + ((process.env.TRAVIS_BUILD_NUMBER) ? process.env.TRAVIS_BUILD_NUMBER : Math.floor(new Date() / 1000))
}

pact.publishPacts(opts)
.then(() => {
console.log('Pact contract publishing complete!')
console.log('')
console.log('Head over to https://test.pact.dius.com.au/ and login with')
console.log('=> Username: dXfltyFMgNOFZAxr8io9wJ37iUpY42M')
console.log('=> Password: O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1')
console.log('to see your published contracts.')
})
.catch(e => {
console.log('Pact contract publishing failed: ', e)
})
Loading

0 comments on commit 641e0e7

Please sign in to comment.