Skip to content

Commit

Permalink
Former JR port ReferenceManagerTestUtils now references SharedJRResou…
Browse files Browse the repository at this point in the history
…rceService

**SharedJRResourceService:**

- Subclass of `JRResourceService` which only allows initialization as a singleton (stored as module-private state)
- Automatically resets its internal state before and after every test run

**ReferenceManagerTestUtils:** this was previously a stub porting the same interface from JavaRosa. It is now updated to use the `SharedJRResourceService` singleton’s state.
  • Loading branch information
eyelidlessness committed Nov 25, 2024
1 parent 3d58132 commit 4fa77ba
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 56 deletions.
84 changes: 28 additions & 56 deletions packages/scenario/src/jr/reference/ReferenceManagerTestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,39 @@
import type { EngineConfig, InitializeFormOptions } from '@getodk/xforms-engine';
import { afterEach, beforeEach } from 'vitest';
import type { JavaNIOPath } from '../../java/nio/Path.ts';
import type { TextFileResourcePath } from '../file/TextFileResourcePath.ts';

/**
* @todo This is incomplete! It was intended to add preliminary support for
* resource loading consistent with setup in ported JavaRosa tests. Since we
* don't yet have any non-form resource loading logic, we'd have no way of
* exercising the actual functionality. As such, this is currently a sketch of
* what a basis for that might look like in terms of JavaRosa interface
* compatibility, test-scoped setup and teardown. When it does become relevant,
* it will likely intersect with {@link TextFileResourcePath} (or some other
* similar interface to resource fixtures) to service the pertinent resources as
* the engine requests them (via {@link EngineConfig}'s `fetchResource` option).
*/
class ResourceManager {
constructor(
readonly path: JavaNIOPath,
readonly jrResourceBasePaths: readonly string[]
) {}
}

let resourceManagers: ResourceManager[] = [];

beforeEach(() => {
resourceManagers = [];
});

afterEach(() => {
resourceManagers = [];
});
import { SharedJRResourceService } from '../../resources/SharedJRResourceService.ts';

/**
* **PORTING NOTES**
*
* The name {@link schemes} has been preserved in the signature of this function
* (corresponding to JavaRosa's static method of the same name). It somewhat
* unintuitively **does not** refer to a URL scheme (i.e. `jr:`), but rather the
* first path segment in a `jr:` resource template URL. For instance, if a form
* references a file resource `jr://file/external-data.geojson`, a test may set
* up access to that resource by calling this function and specifying `"files"`
* as a "scheme".
*
* - - -
*
* Exposed as a plain function; addresses pertinent aspects of the semantic
* intent of JavaRosa's same-named static method on the
* `ReferenceManagerTestUtils` class.
* This signature is preserved as a reference to the equivalent JavaRosa test
* setup interface. Some time was spent tracing the actual setup behavior, and
* it was determined (and since confirmed) that ultimately for test purposes the
* intent is to register a set of file system paths which are available for
* resolving fixtures and fixture resources.
*
* Significant divergences:
* As such, the actual behavior when calling this function produces the
* following minimal equivalent behavior:
*
* 1. Returns `void`, where JavaRosa's equivalent returns a `ReferenceManager`
* (which, per @lognaturel, "nobody likes [...] Don't look :smile:"). This
* appears to be safe for now, as there are no current references to its
* return value.
* 1. When called, any state produced by a prior call is reset.
* 2. The string representation of {@link path} establishes a common base file
* system path for all state produced by the current call.
* 3. For each value in {@link schemes} (naming preserved from JavaRosa), a file
* system path is produced by concatenating that as a subdirectory of that
* common base path.
* 4. Any logic in the active running test will serve fixture resources from the
* set of file system paths produced by the above steps.
*
* 2. While also implicitly stateful, the intent is to keep that state scoped as
* clearly as possible to a given test (its state being tracked and cleaned
* up in an `afterEach` controlled locally in this module as well), and as
* minimal as possible to set up the web forms engine's closest semantic
* equivalent (the configuration of `config.fetchResource` in
* {@link InitializeFormOptions}).
* **Implicitly**, the same state is cleared before and after each test, to
* avoid establishing shared state between tests which might cause them to
* become dependent on ordering of test runs.
*/
export const setUpSimpleReferenceManager = (path: JavaNIOPath, ...schemes: string[]): void => {
resourceManagers.push(new ResourceManager(path, schemes));
const service = SharedJRResourceService.init();

service.activateFixtures(path.toAbsolutePath().toString(), schemes, {
get suppressMissingFixturesDirectoryWarning(): boolean {
const stack = new Error().stack;

return stack?.includes('configureReferenceManagerIncorrectly') ?? false;
},
});
};
26 changes: 26 additions & 0 deletions packages/scenario/src/resources/SharedJRResourceService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { JRResourceService } from '@getodk/common/jr-resources/JRResourceService.ts';
import { afterEach, beforeEach } from 'vitest';

let state: SharedJRResourceService | null = null;

export class SharedJRResourceService extends JRResourceService {
static init(): SharedJRResourceService {
if (state == null) {
state = new this();
}

return state;
}

private constructor() {
super();

beforeEach(() => {
this.reset();
});

afterEach(() => {
this.reset();
});
}
}

0 comments on commit 4fa77ba

Please sign in to comment.