Skip to content

Commit

Permalink
figured out a more robust mocking pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
josephjclark committed Mar 10, 2024
1 parent 9b25167 commit f48a9b4
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 60 deletions.
67 changes: 22 additions & 45 deletions packages/msgraph/src/mock/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,24 @@ import { fixtures } from './fixtures';
* We need to document this in a way that the playground can use
*/

// first step: mock with default data each msgraph function

// ok that's fun, it's a http client

// So this DOES use undici. So I think I can just write interceptors, rght?

let mockAgent;
let mockPool;

// TODO this was copied out of util but it should be a common helper
// actually we don't need this
// export function getBaseUrl(state) {
// const{ resource, apiVersion} = state.configuration
// // if (isValidHttpUrl(resource)) return resource;

// const pathSuffix = apiVersion
// ? `${apiVersion}/${resource}`
// : `v1.0/${resource}`;
// return `https://graph.microsoft.com/${pathSuffix}`;
// }

// To make custom overrides easier, export some stanadard patterns
export const patterns = {
// TODO the regex might be a bit hard here, as we
// need to distinguish the get drive patterns
drives: /\/drives\//
}

export const enable = (state) => {
// name: { pattern, data, options }
const defaultRoutes = {
'drives': { pattern: patterns.drives, data: fixtures.driveResponse }
}

export const enable = (state, routes = {}) => {
// TODO if an agent already exists, should we destroy it?

// set the global dispacher on undici
mockAgent = new MockAgent();

Expand All @@ -48,37 +37,25 @@ export const enable = (state) => {

mockPool = mockAgent.get('https://graph.microsoft.com');

enableDefaultRoutes();
}

// export const reset = (state) => {
// return enable(state)
// }

export const disable = () => {
throw "unimplemented"
}
const mockRoutes = {
...defaultRoutes,
...routes
}

/**
* The problems with this are:
* 1) When I register a persistent route, there's no way
* to disable it
* 2) The first route to bind will always win, so custom
* overrides basically don't work.
* Bugger.
*/
export const enableDefaultRoutes = () => {
mockRoute(patterns.drives, fixtures.driveResponse)
// Set up all the mock routes
for (const name in mockRoutes) {
const { pattern, data, options } = mockRoutes[name];
mockRoute(pattern, data, options)
}
}

// API to enable a particular path to be mocked
export const mockRoute = (path, data, options = {}) => {

const jsonResponse = {
headers: {
'Content-Type': 'application/json',
},
};
const jsonResponse = {
headers: {
'Content-Type': 'application/json',
},
};

const { method = 'GET', headers, once = false } = options
const scope = mockPool.intercept({
Expand Down
4 changes: 2 additions & 2 deletions packages/msgraph/src/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const getRequestHandler = () => {
/** Alternative, standardised, mock handler */

// The runtime itself will call this to flick the whole thing into mock mode
export const enableMock = (state) => {
enable(state)
export const enableMock = (state, routes) => {
return enable(state, routes);
}

// Every adator uses this API to override mock mode
Expand Down
2 changes: 1 addition & 1 deletion packages/msgraph/test/impl.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import * as impl from '../src/impl';
import { fixtures } from './fixtures';
import { fixtures } from '../src/mock/fixtures';

describe('getDrive', () => {
// look how simple this unit test is now
Expand Down
26 changes: 14 additions & 12 deletions packages/msgraph/test/mock.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ import Adaptor from '../src/index.js'

const defaultState = { configuration: {resource: 'x'}, drives: {}};

Adaptor.enableMock(defaultState);

// Test all the default mock behaviours
describe('default values', () => {
before(() => {
Adaptor.enableMock(defaultState);
});

// These can all use the default mock
it('getDrive', async () => {
const state = { ...defaultState };

Expand All @@ -32,19 +36,17 @@ describe('default values', () => {
})
})

// TODO this doesn't work with Undici :(
// Which means we don't have sufficient control of the mock
describe.skip('custom values', () => {
describe('custom values', () => {
it('getDrive', async () => {
const state = { ...defaultState };
Adaptor.enableMock(defaultState, {
'drives': {
pattern: patterns.drives,
data: { x: 22 },
options: { once: true }
}
});

// This should override the default mock... (forever)
// This is annoying, I think the first mock to bind is the winner in case of a conflict
// That doesn't suit me!
// A shame because this is actually a really nice pattern
Adaptor.mock(patterns.drives, {
x: 22
})
const state = { ...defaultState };

const result = await Adaptor.getDrive({ id: 'b!YXzpkoLwR06bxC8tNdg71m_' })(state)
expect(result.drives).to.eql({ default: { x: 22 } })
Expand Down

0 comments on commit f48a9b4

Please sign in to comment.