Skip to content

Instantly share code, notes, and snippets.

@mattwynne
Created January 6, 2021 10:26
Show Gist options
  • Save mattwynne/0143193385ebaf1b58d24aad4a70d159 to your computer and use it in GitHub Desktop.
Save mattwynne/0143193385ebaf1b58d24aad4a70d159 to your computer and use it in GitHub Desktop.
Problem with mocha + pact bailing early
$ yarn git mocha -g GitDocumentStoreSession 5.6s  Wed 6 Jan 10:23:22 2021
yarn run v1.22.5
$ yarn workspace gherkin-editor-git mocha -g GitDocumentStoreSession
$ /Users/matt/projects/gherkin-editor/node_modules/.bin/mocha -g GitDocumentStoreSession
GitDocumentStoreSession
finding a Document by location
1) finds a Document at the location
Pact verification failed!
Actual interactions do not match expected interactions for mock MockService.
Missing requests:
GET /repos/a-repo-id/branches/a-branch/commits?path=path%2Fto%2Ffeatures%2FServeCoffee.feature
GET /repos/a-repo-id/commits/a-commit-sha
See /Users/matt/projects/gherkin-editor/logs/gherkin-editor-git-en-boite.pact.log for details.
2) "after each" hook for "finds a Document at the location"
0 passing (1s)
2 failing
1) GitDocumentStoreSession
finding a Document by location
finds a Document at the location:
AssertionError:
Expected: a promise fulfilled with {"basepath":"path/to/features","content":"Feature: Serve Coffee","fileName":"ServeCoffee.feature","validationErrors":[],"location":"path/to/features/ServeCoffee.feature"}
but: fulfillment value: was {"basepath":"path/to/features","content":"# TODO: call getLastChangeTo()","validationErrors":["Document needs a Feature"],"location":{"basepath":"path/to/features"}}
at /Users/matt/projects/gherkin-editor/node_modules/hamjest/lib/promiseThat.js:41:5
at processImmediate (internal/timers.js:461:21)
From previous event:
at Object.promiseThat (/Users/matt/projects/gherkin-editor/node_modules/hamjest/lib/promiseThat.js:16:53)
at Context.<anonymous> (src/GitDocumentStoreSession.spec.ts:127:13)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
2) GitDocumentStoreSession
"after each" hook for "finds a Document at the location":
Error: Pact verification failed - expected interactions did not match actual.
at new VerificationError (/Users/matt/projects/gherkin-editor/node_modules/@pact-foundation/pact/errors/verificationError.js:19:42)
at /Users/matt/projects/gherkin-editor/node_modules/@pact-foundation/src/httpPact.ts:124:17
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at Context.<anonymous> (src/GitDocumentStoreSession.spec.ts:17:25)
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed.
Exit code: 2
Command: /Users/matt/.config/nvm/14.15.1/bin/node
Arguments: /usr/local/Cellar/yarn/1.22.5/libexec/lib/cli.js mocha -g GitDocumentStoreSession
Directory: /Users/matt/projects/gherkin-editor/packages/git
Output:
info Visit https://yarnpkg.com/en/docs/cli/workspace for documentation about this command.
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
I, [2021-01-06T10:23:46.759973 #405] INFO -- : Registered expected interaction POST /repos/a-repo-id/branches/a-branch/commits
D, [2021-01-06T10:23:46.760333 #405] DEBUG -- : {
"description": "a new file to commit",
"providerState": "a repo with a branch",
"request": {
"method": "POST",
"path": "/repos/a-repo-id/branches/a-branch/commits",
"headers": {
"Content-Type": "application/json"
},
"body": {
"files": [
{
"path": "path/to/features/ServeCoffee.feature",
"content": "Feature: Serve Coffee"
}
],
"author": {
"name": "An Author",
"email": "author@example.com"
},
"message": "Create serve coffee feature"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"body": {
}
},
"metadata": null
}
I, [2021-01-06T10:23:46.772267 #405] INFO -- : Received request POST /repos/a-repo-id/branches/a-branch/commits
D, [2021-01-06T10:23:46.772467 #405] DEBUG -- : {
"path": "/repos/a-repo-id/branches/a-branch/commits",
"query": "",
"method": "post",
"body": {
"files": [
{
"path": "path/to/features/ServeCoffee.feature",
"content": "Feature: Serve Coffee"
}
],
"author": {
"name": "An Author",
"email": "author@example.com"
},
"message": "Create serve coffee feature"
},
"headers": {
"Content-Length": "192",
"Content-Type": "application/json",
"Accept": "*/*",
"User-Agent": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)",
"Accept-Encoding": "gzip,deflate",
"Connection": "close",
"Host": "localhost:1339",
"Version": "HTTP/1.1"
}
}
I, [2021-01-06T10:23:46.773078 #405] INFO -- : Found matching response for POST /repos/a-repo-id/branches/a-branch/commits
D, [2021-01-06T10:23:46.773189 #405] DEBUG -- : {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"body": {
}
}
I, [2021-01-06T10:23:46.779279 #405] INFO -- : Registered expected interaction GET /repos/a-repo-id/branches/a-branch/commits?path=path%2Fto%2Ffeatures%2FServeCoffee.feature
D, [2021-01-06T10:23:46.779540 #405] DEBUG -- : {
"description": "a request for the commits on the branch",
"providerState": "a repo with a branch with a single commit adding a new file",
"request": {
"method": "GET",
"path": "/repos/a-repo-id/branches/a-branch/commits",
"query": {
"path": [
{
"json_class": "Pact::SomethingLike",
"contents": "path/to/features/ServeCoffee.feature"
}
]
},
"headers": {
"Content-Type": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"body": {
"commits": [
{
"author": {
"name": "An Author",
"email": "author@example.com"
},
"message": "Create serve coffee feature",
"link": "/repos/a-repo-id/commits/a-commit-id"
}
]
}
},
"metadata": null
}
I, [2021-01-06T10:23:46.785841 #405] INFO -- : Registered expected interaction GET /repos/a-repo-id/commits/a-commit-sha
D, [2021-01-06T10:23:46.785972 #405] DEBUG -- : {
"description": "a request for the commit",
"providerState": "a repo with a branch with a single commit adding a new file",
"request": {
"method": "GET",
"path": "/repos/a-repo-id/commits/a-commit-sha",
"headers": {
"Content-Type": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"body": {
"author": {
"name": "An Author",
"email": "author@example.com"
},
"message": "Create serve coffee feature",
"files": [
{
"path": "path/to/features/ServeCoffee.feature",
"content": "Feature: Serve Coffee"
}
]
}
},
"metadata": null
}
W, [2021-01-06T10:23:46.796735 #405] WARN -- : Verifying - actual interactions do not match expected interactions.
Missing requests:
GET /repos/a-repo-id/branches/a-branch/commits?path=path%2Fto%2Ffeatures%2FServeCoffee.feature
GET /repos/a-repo-id/commits/a-commit-sha
W, [2021-01-06T10:23:46.796805 #405] WARN -- : Missing requests:
GET /repos/a-repo-id/branches/a-branch/commits?path=path%2Fto%2Ffeatures%2FServeCoffee.feature
GET /repos/a-repo-id/commits/a-commit-sha
I, [2021-01-06T10:23:46.802526 #405] INFO -- : Cleared interactions
I, [2021-01-06T10:23:46.808134 #405] INFO -- : Writing pact for GitEnBoite to /Users/matt/projects/gherkin-editor/pacts/gherkineditor-gitenboite.json
import { InteractionObject, Pact } from '@pact-foundation/pact'
import { like } from '@pact-foundation/pact/dsl/matchers'
import { Author, ChangeDescription, DocumentLocation, DocumentNotFound, GherkinDocument } from 'gherkin-editor-core'
import { equalTo, fulfilled, instanceOf, promiseThat, rejected } from 'hamjest'
import path = require('path')
import { GitDocumentStoreSession } from './GitDocumentStoreSession'
describe(GitDocumentStoreSession.name, () => {
before(async function () {
this.timeout(10000)
await mockService.setup()
})
after(async () => await mockService.finalize())
afterEach(async () => await mockService.verify())
const PORT = 1339
const mockService = new Pact({
consumer: 'GherkinEditor',
provider: 'GitEnBoite',
port: PORT,
log: path.resolve(__dirname, '..', '..', '..', 'logs', 'gherkin-editor-git-en-boite.pact.log'),
logLevel: 'warn',
dir: path.resolve(__dirname, '..', '..', '..', 'pacts'),
})
const postCommitToBranch = (
document: GherkinDocument,
author: Author,
message: ChangeDescription
): InteractionObject => {
const file = {
path: document.location.toString(),
content: document.content,
}
return {
state: 'a repo with a branch',
uponReceiving: 'a new file to commit',
withRequest: {
method: 'POST',
path: '/repos/a-repo-id/branches/a-branch/commits',
headers: { 'Content-Type': 'application/json' },
body: { files: [file], author, message },
},
willRespondWith: {
status: 200,
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: {},
},
}
}
const getSomeCommitsForPath = (
path: string,
author: Author,
message: ChangeDescription,
commitIds: string[]
): InteractionObject => ({
state: 'a repo with a branch with a single commit adding a new file',
uponReceiving: 'a request for the commits on the branch',
withRequest: {
method: 'GET',
path: '/repos/a-repo-id/branches/a-branch/commits',
query: {
path: like(path),
},
headers: { 'Content-Type': 'application/json' },
},
willRespondWith: {
status: 200,
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: {
commits: commitIds.map((id) => ({
author,
message,
link: `/repos/a-repo-id/commits/${id}`,
})),
},
},
})
const getCommitThatCreated = (
document: GherkinDocument,
author: Author,
message: ChangeDescription
): InteractionObject => {
const file = {
path: document.location.toString(),
content: document.content,
}
return {
state: 'a repo with a branch with a single commit adding a new file',
uponReceiving: 'a request for the commit',
withRequest: {
method: 'GET',
path: '/repos/a-repo-id/commits/a-commit-sha',
headers: { 'Content-Type': 'application/json' },
},
willRespondWith: {
status: 200,
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: {
author,
message,
files: [file], // TODO: should we return blob refs here instead of file contents, then have another endpoint for the blob? Basically make this like `git ls-tree <ref> -r`
},
},
}
}
describe('finding a Document by location', () => {
const author = new Author('An Author', 'author@example.com')
const message = new ChangeDescription('Create serve coffee feature')
it('finds a Document at the location', async () => {
const session = new GitDocumentStoreSession(`http://localhost:${PORT}`, 'a-repo-id', 'a-branch')
const document = GherkinDocument.parse('path/to/features', 'Feature: Serve Coffee')
const location = document.location
await mockService.addInteraction(postCommitToBranch(document, author, message))
await session.saveDocument(document, author, message)
await mockService.addInteraction(
getSomeCommitsForPath(document.location.toString(), author, message, ['a-commit-id'])
)
await mockService.addInteraction(getCommitThatCreated(document, author, message))
await promiseThat(session.documentAt(location), fulfilled(equalTo(document)))
})
it('throws a DocumentNotFound error when there is no Document at the location', async () => {
const session = new GitDocumentStoreSession(`http://localhost:${PORT}`, 'a-repo-id', 'a-branch')
const location = DocumentLocation.fromPath('/path/to/inexisting.feature')
await mockService.addInteraction(getSomeCommitsForPath(location.toString(), author, message, []))
await promiseThat(session.documentAt(location), rejected(instanceOf(DocumentNotFound)))
})
it('fails', async () => {
await promiseThat(Promise.reject(), rejected())
})
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment