Skip to content

Commit

Permalink
Merge pull request #39 from YizYah/transactionType
Browse files Browse the repository at this point in the history
feat: record transaction type
  • Loading branch information
YizYah authored Nov 9, 2021
2 parents 8605de3 + 0319d22 commit a1d3270
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 23 deletions.
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ In the extraordinarily unlikely event that you have an object in your data that

### Mock Session Generation

There are two functions for generating sessions that produce mock outptu. These can be used for confirming that output is what you expect it to be.
There are two functions for generating sessions that produce mock output. These can be used for confirming that output is what you expect it to be.

### Generation from a Query Set

Expand Down Expand Up @@ -247,6 +247,32 @@ The `sessionRunMock` function should have as parameters `(query: string, params:

In theory, you could create a session which emulates your entire database for all of the queries in your tests, and simply reuse the mock session in all of your tests. Note that you can also throw errors if you are testing for them.

### Testing Transactions

Transactions can be called in your test as easily as directly calling `.run()`.

For instance:

```typescript
const session = mockSessionFromQuerySet(querySet)
const output: any = await session.readTransaction((tx: any) =>
tx.run(query, params))
// assert that output is expected
```

If you want to ensure that a particular transaction type was executed, you can look at `summary.transactionType` in the output. The value of `transactionType` will be either `READ` or `WRITE`.

For instance:

```typescript
const session = mockSessionFromFunction(sessionRunMock)

const output: any = await session.writeTransaction((tx: any) =>
tx.run('', { foo: "bar" }))

t.is(output.summary.transactionType, 'WRITE')
```

### Mock Driver Generation

There are cases where you will have to generate a mock driver. The most typical use case is for mocking an Apollo Server that uses the [@neo4j/graphql](https://www.npmjs.com/package/@neo4j/graphql) library.
Expand Down
9 changes: 7 additions & 2 deletions src/custom/session/mockSessionFromFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ export function mockSessionFromFunction(mockRun: Function): Session {
const fakeSession = driver.session()
fakeSession.run = mockRun

const mockBeginTransaction = () => {

const mockBeginTransaction = (transactionType: string) => {
let _isOpen = true;
return {
run: mockRun,
run: async (query: string, params: any) => {
const output = await mockRun(query, params)
output.summary.transactionType = transactionType
return output
},
commit: () => {
_isOpen = false;
return Promise.resolve()
Expand Down
22 changes: 9 additions & 13 deletions src/custom/session/mockSessionFromQuerySet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,13 @@ function mockSessionFromQuerySet(querySet: QuerySpec[]): Session {

const mockRun = async (query: string, params: any) => {
let queryMatched = false;
// querySet.map((querySpec: QuerySpec) => {
// if (removeExtraWhite(querySpec.query) === removeExtraWhite(query)) {
// queryMatched = true;
// if (!querySpec.params || isSubset(params, querySpec.params)) { // was: JSON.stringify(querySpec.params) === JSON.stringify(params)
// output = storedToLive(querySpec.output);
// }
// }
// });

for (let index = 0; index < querySet.length; index++) {
const querySpec: QuerySpec = querySet[index];

if (removeExtraWhite(querySpec.query) === removeExtraWhite(query)) {
queryMatched = true;
if (!querySpec.params || isSubset(params, querySpec.params)) {
if (!querySpec.params || isSubset(params, querySpec.params)) {
return storedToLive(querySpec.output);
}
}
Expand All @@ -79,10 +71,14 @@ function mockSessionFromQuerySet(querySet: QuerySpec[]): Session {
throw new Error(errorMessageNoMatchedQuery);
};

const mockBeginTransaction = () => {
fakeSession._beginTransaction = function mockBeginTransaction(transactionType: string) {
let _isOpen = true;
return {
run: mockRun,
run: async (query: string, params: any) => {
const output = await mockRun(query, params)
output.summary.transactionType = transactionType
return output
},
commit: () => {
_isOpen = false;
return Promise.resolve();
Expand All @@ -93,10 +89,10 @@ function mockSessionFromQuerySet(querySet: QuerySpec[]): Session {
},
isOpen: () => _isOpen,
};
};
}

fakeSession.run = mockRun;
fakeSession._beginTransaction = mockBeginTransaction;
// fakeSession._beginTransaction = mockBeginTransaction;

return fakeSession;
}
Expand Down
18 changes: 14 additions & 4 deletions test/custom/mockSessionFromFunction.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import test from 'ava'
const mockSessionFromFunction = require("../../src/custom/session/mockSessionFromFunction")
// import { mockSessionFromFunction} from "../../src/custom/session/mockSessionFromFunction"
import {sampleRecordList} from "./data/sampleRecordList";
import {dataToLive} from "../../src/custom/response/dataToLive";
import { sampleRecordList } from "./data/sampleRecordList";
import { dataToLive } from "../../src/custom/response/dataToLive";

const sessionRunMock = (query: string, params: any) => {
return dataToLive(sampleRecordList);
Expand All @@ -11,13 +11,23 @@ const sessionRunMock = (query: string, params: any) => {
test('mockSessionFromFunction', t => {
const session = mockSessionFromFunction(sessionRunMock)
t.is(session.run, sessionRunMock)
t.not(session.run, ()=>{return 1})
t.not(session.run, () => { return 1 })
})

test('mockSessionFromFunction works with transacation', async t => {
const session = mockSessionFromFunction(sessionRunMock)

const output: any = await session.writeTransaction((tx: any) =>
tx.run('', { foo: "bar" }))

t.is(output.summary.transactionType, 'WRITE')
})


test('mockSessionFromFunction with transacation', async t => {
const session = mockSessionFromFunction(sessionRunMock)
const tx = session._beginTransaction()
t.is(tx.run, sessionRunMock)
// t.is(tx.run, sessionRunMock)
t.is(tx.isOpen(), true)
t.is(await tx.rollback(), await Promise.resolve())
t.is(await tx.commit(), await Promise.resolve())
Expand Down
49 changes: 46 additions & 3 deletions test/custom/mockSessionFromQuerySet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,40 @@ const expectedOutput3 = {
]
}

const expectedOutput4: StoredResponse = {
records:
[
{
"keys": [
"role"
],
"length": 1,
"_fields": [
"Moderator"
],
"_fieldLookup": {
"role": 0
}
},
{
"keys": [
"role"
],
"length": 1,
"_fields": [
"customer"
],
"_fieldLookup": {
"role": 0
}
}
],
summary: {
transactionType: 'READ'
}
}


const query = 'foo'
const query2 = 'foobaroo'
const noParamsQuery = 'noparams'
Expand Down Expand Up @@ -109,6 +143,15 @@ test('mockSessionFromQuerySet returns correct output', async t => {
t.deepEqual(stripUpdates(output), stripUpdates(storedToLive(expectedOutput)))
})


test('mockSessionFromQuerySet works called with transaction', async t => {
const session = mockSessionFromQuerySet(querySet)
const output: any = await session.readTransaction((tx: any) =>
tx.run(query, params))

t.like(stripUpdates(output), stripUpdates(storedToLive(expectedOutput4)))
})

test('mockSessionFromQuerySet returns correct output even with extra params', async t => {
const session = mockSessionFromQuerySet(querySet)
const output = await session.run(query, { 'boo': 'bar', 'extra': 'should be ignored' })
Expand All @@ -125,11 +168,11 @@ test('mockSessionFromQuerySet evaluates in order', async t => {
const session = mockSessionFromQuerySet(querySet)

// this will match the first query result
const output = await session.run(query2, { 'x': 'y'})
const output = await session.run(query2, { 'x': 'y' })
t.like(stripUpdates(output), stripUpdates(storedToLive(expectedOutput)))

// this will match the second query result
const output2 = await session.run(query2, { 'x': 'z'})
const output2 = await session.run(query2, { 'x': 'z' })
t.like(stripUpdates(output2), stripUpdates(storedToLive(expectedOutput3)))

})
Expand All @@ -138,7 +181,7 @@ test('mockSessionFromQuerySet evaluates in order', async t => {
test('mockSessionFromQuerySet takes no params', async t => {
const session = mockSessionFromQuerySet(querySet)
const output = await session.run(noParamsQuery)
t.like(stripUpdates(output), stripUpdates(storedToLive(expectedOutput2)) )
t.like(stripUpdates(output), stripUpdates(storedToLive(expectedOutput2)))
// t.like(output, storedToLive(expectedOutput2))
})

Expand Down

0 comments on commit a1d3270

Please sign in to comment.