What is the best approach to repurpose a jest test for various implementations of a shared interface?

I'm facing a challenge:

describe("Given a config repository", () => {
    let target: ConfigRepository;

    beforeEach(() => {
        target = InMemoryConfigRepository();
    });

    test("When creating a new config, Then it is persisted properly", async () => {
        const key = "key";
        const namespace = "namespace";
        const result = await target.upsert({
            key,
            namespace,
            value: "value",
            teamId: "teamId",
        })();
        const configs = await target.findAll()();

        expect(result._tag).toEqual("Right");
        expect(configs.length).toBe(1);
        expect(configs.map((c) => c.key)).toEqual([key]);
    });
});

This test can be used to validate any implementation of my interface:

export type ConfigRepository = {
    get: <T extends RequiredJsonObject>(
        props: ConfigurationProperties<T>
    ) => TE.TaskEither<DatabaseError | MissingConfigError, ConfigEntity[]>;
    findAll(): T.Task<ConfigEntity[]>;
    upsert: (
        config: UnsavedConfig
    ) => TE.TaskEither<DatabaseError, ConfigEntity>;
};

The challenge I'm encountering is how to adapt this test for different implementations of the same interface, such as testing a PrismaConfigRepository. Any suggestions on how I could approach this?

Answer №1

If you're looking to implement a Parameterized Test, one approach is using the .each method in Jest. This involves passing the constructor of each class that implements the ConfigRepository interface as a parameter and creating instances within the beforeEach function instead of always instantiating an InMemoryConfigRepository.

Here's a rough example of how this could be structured:

describe.each(
   [[InMemoryConfigRepository],[PrismaConfigRepository]]
)(
   "Given a config repository (implementation no. %#)", 
   (configRepositoryConstructor: new () => ConfigRepository) => {
        let target: ConfigRepository;

        beforeEach(() => {
            target = configRepositoryConstructor();
        });

        test("When creating a new config, Then it is persisted properly", async () => {
           // current test implementation
        });
   }
);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

TypeScript purity - "The variable exports is not defined"

I encountered an issue with my simple client-server TypeScript application where every import statement in my client.ts file triggers a ReferenceError: exports is not defined error in the browser after loading the HTML. Here is the project structure: root ...

Avoid using propTypes for props verification

Looking for a solution to handle multiple props on a button: interface buttonProps { secondary?: boolean; tertiary?: boolean; width?: number; children?: any; icon?: string; } If the button includes an icon without any children, how can ...

Google Cloud PubSub does not automatically resend unacknowledged messages

The answer chosen for this particular question contains some pertinent details I currently have a subscription set up with the following parameters: https://i.stack.imgur.com/Bn0d4.png along with the following code snippet: const subscription = this.pub ...

Display the current date in YYYY/MM/DD format using a single method in React and TypeScript

Is there a better way to retrieve YYYY/MM/DD data using just one method? I attempted the following: date = created_at // from API const sendDate = `${String((date.getMonth() + 1)).padStart(2, '0')}${String(date.getDate()).padStart(2, '0&apos ...

Typescript raises an issue regarding a React component's optional prop potentially being undefined

I have a basic React component that looks like this: interface ComponentProperties { onClick?: () => void; } const CustomComponent = (properties: ComponentProperties) => { if (!properties.onClick) { return <></>; } ...

What are the steps for testing React components when they are wrapped by ThemeProvider/withStyle?

Is there a way to properly test a component that is wrapped with withStyle, as it seems the theme object does not pass through the component. Any suggestions on best practices for achieving this? I am considering using createShallow() and dive() methods t ...

What is the best way to retrieve a value from an array?

Using ASP.net Core, I receive information from my API. In Angular, the data looks like this: 0: {Id: 3, Role_Name: 'ITAdmin'} 1: {Id: 4, Role_Name: 'Admin'} 2: {Id: 5, Role_Name: 'user'} I want to extract values from this arr ...

Issue with service injection within a singleton service in Angular2

Currently, I have two services in my application. ServiceA is non-singleton and provided to components through the Providers array, while ServiceB is a singleton that is listed in its module's Providers array. Both services work perfectly fine indepen ...

What is the best way to structure a nested object model in Angular?

Issue occurred when trying to assign the this.model.teamMembersDto.roleDto to teamMembersDto. The error message states that the property roleDto does not exist on type TeamMembersDropdownDto[], even though it is nested under teamMembersDto. If you look at ...

Encountered an issue when attempting to establish a connection with the REST

I am encountering an issue with connecting to a web service deployed on an Apache server using Jersey. The error message I receive is: Failed to load http://192.168.1.200:8199/CheckinnWeb/webapi/myresource/query: No 'Access-Control-Allow-Origin' ...

Encountering build:web failure within npm script due to TypeScript

Our project is utilizing the expo-cli as a local dependency in order to execute build:web from an npm script without requiring the global installation of expo-cli. However, when we run npm run build:web, we encounter the following exception. To isolate th ...

Concealing a navigation tab with Angular4 in Typescript: A tutorial

I have successfully implemented 3 tabs in my Angular 4 project. At the moment, I am focusing on working with the first two tabs and planning to tackle the third tab in the near future. To keep things clean and organized, I am looking to use JavaScript/Typ ...

Using React, PIXI, and Zustand can sometimes lead to stale state issues when handling mouse events

I currently have a Pixi canvas that utilizes pointer handlers. Users are able to click on a point within a 'sequence' and move it. Recently, I came across an issue with the mouse handlers having stale state. To resolve this, I began recreating t ...

Exploring the optimal approach for distinguishing between numbers and strings in a JavaScript/Typescript class

I recently encountered a situation with my Typescript/React solution where I defined a property as a number and set the input type to "number", but when the state value was placed in an input field, it would change to a string unless properly handled. In ...

How to override or redefine a TypeScript class with generics

Presently, I am immersed in a project involving three.js and TypeScript. It has come to my attention that for organizing elements, the Group class is highly recommended. However, I have noticed that the type definitions for Group do not include a feature l ...

How can you utilize createRef in React Native when working with TypeScript?

Trying to understand the usage of React.createRef() in react native with typescript, I encountered some errors while using it // ... circleRef = React.createRef(); componentDidMount() { this.circleRef.current.setNativeProps({ someProperty ...

Encountered an issue during installation: Error message states that Typings command was not

I've encountered permission errors with npm, so I decided to reinstall it. However, I'm facing an issue with the 'typings' part where it displays a 'typings: command not found' error. This problem seems to be related to Angula ...

Issue with Angular: RouterLinkActive fails to work properly with formControlName

I am currently working on a vertical navigation bar that allows the user to navigate to different components. However, I am facing an issue where when I click on a list item, it's supposed to be active but I have to click on it to navigate to the comp ...

The utility of commander.js demonstrated in a straightforward example: utilizing a single file argument

Many developers rely on the commander npm package for command-line parsing. I am considering using it as well due to its advanced functionality, such as commands, help, and option flags. For my initial program version, I only require commander to parse ar ...

Conflicting React types found in pnpm monorepo

In the process of converting an inherited monorepo from yarn+lerna to pnpm workspaces, I am encountering some issues. Specifically, there are mismatching React versions causing errors in typescript. It seems that TypeScript is not recognizing the closest @ ...