Skip to content

Commit

Permalink
Fix issues while mocking graphs in tests (#134)
Browse files Browse the repository at this point in the history
Fix issues while mocking graphs in tests

This PR fixes two issues that happened only while mocking graphs:

1. Requiring a singleton graph before it was mocked resulted in Obsidian always using the original graph instead of the mock
2. Obsidian's graph registry, which is intended to be a singleton, was instantiated multiple times. Apparently this was caused by issues with Jest/Node compatibility
  • Loading branch information
guyca authored Mar 19, 2024
1 parent fd1ef99 commit e9be75f
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-obsidian",
"version": "2.2.0",
"version": "2.3.0-rc.1",
"description": "Dependency injection framework for React and React Native applications",
"scripts": {
"prepack": "npm run lint && tsc --project tsconfig.prod.json",
Expand Down Expand Up @@ -53,7 +53,7 @@
"eslint-plugin-local-rules": "^1.3.2",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-unused-imports": "2.x.x",
"eslint-plugin-unused-imports": "3.1.x",
"husky": "8.0.1",
"jest": "29.5.x",
"jest-create-mock-instance": "2.0.0",
Expand Down
21 changes: 20 additions & 1 deletion src/graph/registry/GraphRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ export class GraphRegistry {
return Reflect.getMetadata('isLifecycleBound', Graph) ?? false;
}

clearGraphAfterItWasMockedInTests(graphName: string) {
const graphNames = this.nameToInstance.keys();
for (const name of graphNames) {
if (name.match(graphName)) {
const graph = this.nameToInstance.get(name);
if (!graph) return;
const Graph = this.instanceToConstructor.get(graph);
if (!Graph) return;

this.instanceToConstructor.delete(graph);
this.constructorToInstance.get(Graph)!.delete(graph);
this.nameToInstance.delete(graph.name);
}
}
}

clear(graph: Graph) {
const Graph = this.instanceToConstructor.get(graph);
if (!Graph || this.isSingleton(Graph)) return;
Expand All @@ -93,4 +109,7 @@ export class GraphRegistry {
}
}

export default new GraphRegistry();
// @ts-ignore
global.graphRegistry = global.graphRegistry || new GraphRegistry();
// @ts-ignore
export default global.graphRegistry as GraphRegistry;
34 changes: 33 additions & 1 deletion test/integration/mockingGraphs.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from 'react';
import { render } from '@testing-library/react';
import SingletonGraph from '../fixtures/SingletonGraph';
import MainGraph from '../fixtures/MainGraph';
import Subgraph from '../fixtures/Subgraph';
import { Graph, Provides } from '../../src';
import {
Graph,
Obsidian,
Provides,
Singleton,
} from '../../src';
import InjectedComponent from '../fixtures/InjectedComponent';
import { mockGraphs } from '../../testkit';

Expand All @@ -23,6 +29,32 @@ describe('Test doubles', () => {
expect(container.textContent).toBe('MockedContent');
});

it('Mocks graphs when using Obsidian.obtain', () => {
const stringToCompare = Obsidian.obtain(MainGraph).someString();
expect(stringToCompare).toBe('Mocked');
});

it('Mocks graphs when using Obsidian.obtain on a Singleton graph'
+ 'even after the singleton graph was already registered in graph registry', () => {
registerSingletonGraphBeforeMocking();

const stringToCompare = Obsidian.obtain(SingletonGraph).instanceId();
expect(stringToCompare).toBe('MockSingleton');
});

function registerSingletonGraphBeforeMocking() {
Obsidian.obtain(SingletonGraph);
mockGraphs({ SingletonGraph: MockSingletonGraph });
}

@Singleton() @Graph()
class MockSingletonGraph extends SingletonGraph {
@Provides()
override instanceId(): string {
return 'MockSingleton';
}
}

@Graph()
class MockMainGraph extends MainGraph {
@Provides()
Expand Down
10 changes: 10 additions & 0 deletions testkit/mockGraphs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,15 @@ export function mockGraphs(
return resolveChain.proceed(Graph, props);
}
}();

clearRegisteredGraphs(graphNameToGraph);
graphRegistry.addGraphMiddleware(graphMiddleware);
}

function clearRegisteredGraphs(
graphNameToGraph: Record<string, Constructable<ObjectGraph> | ((props: any) => ObjectGraph)>,
) {
for (const graphName of Object.keys(graphNameToGraph)) {
graphRegistry.clearGraphAfterItWasMockedInTests(graphName);
}
}

0 comments on commit e9be75f

Please sign in to comment.