Repository: open-feature/js-sdk (ts)

Issue:
Use in-memory provider for e2e suites
Currently, we use flagd for e2e testing in this repo (see following links). Now that we have in-memory providers for both web and server, we should remove the dependency on flagd and use the in-memory providers for these gherkin suites.

Remove this file: https://github.com/open-feature/js-sdk/blob/main/packages/server/e2e/step-definitions/setup.ts and this file: https://github.com/open-feature/js-sdk/blob/main/packages/client/e2e/step-definitions/setup.ts and configure the in-memory provider in the evaluation.spec gherkin implementations themselves ([here](https://github.com/open-feature/js-sdk/blob/a3799e1b658bafca5ea11528399e7560ef43d3e6/packages/server/e2e/step-definitions/evaluation.spec.ts#L22) and [here](https://github.com/open-feature/js-sdk/blob/a3799e1b658bafca5ea11528399e7560ef43d3e6/packages/client/e2e/step-definitions/evaluation.spec.ts#L20)).

Pull request description:
fix: use in memory provider for e2e suites
## This PR
Removes setup using Flagd Provider and uses In-Memory Provider

Fixes #712


Patch:
diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml
index 69d53fa9..f5290655 100644
--- a/.github/workflows/pr-checks.yaml
+++ b/.github/workflows/pr-checks.yaml
@@ -65,12 +65,6 @@ jobs:
   e2e:
     runs-on: ubuntu-latest
 
-    services:
-      flagd:
-        image: ghcr.io/open-feature/flagd-testbed:latest
-        ports:
-          - 8013:8013
-
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-node@v4
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1d733558..0fb4e515 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -30,11 +30,7 @@ Run tests with `npm test`.
 
 ### End-to-End Tests
 
-The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using [`flagd`](https://github.com/open-feature/flagd). These tests run with the "e2e" npm script. If you'd like to run them locally, you can start the flagd testbed with
-```
-docker run -p 8013:8013 ghcr.io/open-feature/flagd-testbed:latest
-```
-and then run
+The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using in-memory provider. These tests run with the "e2e" npm script. If you'd like to run them locally, follow the steps below:
 ```
 npm run e2e-server
 ```
diff --git a/jest.config.ts b/jest.config.ts
index eeacc3aa..0d1d2e2a 100644
--- a/jest.config.ts
+++ b/jest.config.ts
@@ -138,7 +138,6 @@ export default {
       preset: 'ts-jest',
       testMatch: ['<rootDir>/packages/server/e2e/**/*.spec.ts'],
       modulePathIgnorePatterns: ['.*/node-modules/'],
-      setupFiles: ['<rootDir>/packages/server/e2e/step-definitions/setup.ts'],
       moduleNameMapper: {
         '@openfeature/core': '<rootDir>/packages/shared/src',
       },
@@ -149,7 +148,6 @@ export default {
       preset: 'ts-jest',
       testMatch: ['<rootDir>/packages/client/e2e/**/*.spec.ts'],
       modulePathIgnorePatterns: ['.*/node-modules/'],
-      setupFiles: ['<rootDir>/packages/client/e2e/step-definitions/setup.ts'],
       moduleNameMapper: {
         '^uuid$': require.resolve('uuid'),
         '^(.*)\\.js$': ['$1', '$1.js'],


Test patch:
diff --git a/packages/client/e2e/step-definitions/evaluation.spec.ts b/packages/client/e2e/step-definitions/evaluation.spec.ts
index 017661b7..f03e7680 100644
--- a/packages/client/e2e/step-definitions/evaluation.spec.ts
+++ b/packages/client/e2e/step-definitions/evaluation.spec.ts
@@ -7,7 +7,8 @@ import {
   ResolutionDetails,
   StandardResolutionReasons,
 } from '@openfeature/core';
-import { OpenFeature, ProviderEvents } from '../..';
+import { OpenFeature, ProviderEvents, InMemoryProvider } from '../../src';
+import flagConfiguration from './flags-config';
 // load the feature file.
 const feature = loadFeature('packages/client/e2e/features/evaluation.feature');
 
@@ -17,6 +18,7 @@ const client = OpenFeature.getClient();
 const givenAnOpenfeatureClientIsRegisteredWithCacheDisabled = (
   given: (stepMatcher: string, stepDefinitionCallback: () => void) => void
 ) => {
+  OpenFeature.setProvider(new InMemoryProvider(flagConfiguration));
   given('a provider is registered with cache disabled', () => undefined);
 };
 
@@ -70,10 +72,11 @@ defineFeature(feature, (test) => {
 
     givenAnOpenfeatureClientIsRegisteredWithCacheDisabled(given);
 
+    
     when(
       /^an integer flag with key "(.*)" is evaluated with default value (\d+)$/,
-      (key: string, defaultValue: number) => {
-        value = client.getNumberValue(key, defaultValue);
+      (key: string, defaultValue: string) => {    
+        value = client.getNumberValue(key, Number.parseInt(defaultValue));
       }
     );
 
diff --git a/packages/client/e2e/step-definitions/flags-config.ts b/packages/client/e2e/step-definitions/flags-config.ts
new file mode 100644
index 00000000..17956b13
--- /dev/null
+++ b/packages/client/e2e/step-definitions/flags-config.ts
@@ -0,0 +1,71 @@
+export default {
+  'boolean-flag': {
+    disabled: false,
+    variants: {
+      on: true,
+      off: false,
+    },
+    defaultVariant: 'on',
+  },
+  'string-flag': {
+    disabled: false,
+    variants: {
+      greeting: 'hi',
+      parting: 'bye',
+    },
+    defaultVariant: 'greeting',
+  },
+  'integer-flag': {
+    disabled: false,
+    variants: {
+      one: 1,
+      ten: 10,
+    },
+    defaultVariant: 'ten',
+  },
+  'float-flag': {
+    disabled: false,
+    variants: {
+      tenth: 0.1,
+      half: 0.5,
+    },
+    defaultVariant: 'half',
+  },
+  'object-flag': {
+    disabled: false,
+    variants: {
+      empty: {},
+      template: {
+        showImages: true,
+        title: 'Check out these pics!',
+        imagesPerPage: 100,
+      },
+    },
+    defaultVariant: 'template',
+  },
+  'context-aware': {
+    disabled: false,
+    variants: {
+      internal: 'INTERNAL',
+      external: 'EXTERNAL',
+    },
+    defaultVariant: 'external',
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    contextEvaluator(ctx: any) {
+      const { fn, ln, age, customer } = ctx;
+      if (fn === 'Sulisław' && ln === 'Świętopełk' && age === 29 && customer === false) {
+        return 'internal';
+      } else {
+        return 'external';
+      }
+    },
+  },
+  'wrong-flag': {
+    disabled: false,
+    variants: {
+      one: 'uno',
+      two: 'dos',
+    },
+    defaultVariant: 'one',
+  },
+};
diff --git a/packages/client/e2e/step-definitions/setup.ts b/packages/client/e2e/step-definitions/setup.ts
deleted file mode 100644
index 5f225673..00000000
--- a/packages/client/e2e/step-definitions/setup.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import assert from 'assert';
-import { OpenFeature } from '../..';
-import { FlagdWebProvider } from '@openfeature/flagd-web-provider';
-
-const FLAGD_WEB_NAME = 'flagd-web';
-
-// register the flagd provider before the tests.
-console.log('Setting flagd web provider...');
-OpenFeature.setProvider(new FlagdWebProvider({
-  host: 'localhost',
-  port: 8013,
-  tls: false,
-  maxRetries: -1,
-}));
-assert(
-  OpenFeature.providerMetadata.name === FLAGD_WEB_NAME,
-  new Error(`Expected ${FLAGD_WEB_NAME} provider to be configured, instead got: ${OpenFeature.providerMetadata.name}`)
-);
-console.log('flagd web provider configured!');
diff --git a/packages/server/e2e/step-definitions/evaluation.spec.ts b/packages/server/e2e/step-definitions/evaluation.spec.ts
index 1794ffdb..957bd8fa 100644
--- a/packages/server/e2e/step-definitions/evaluation.spec.ts
+++ b/packages/server/e2e/step-definitions/evaluation.spec.ts
@@ -8,7 +8,8 @@ import {
   StandardResolutionReasons,
   ProviderEvents,
 } from '@openfeature/core';
-import { OpenFeature } from '../..';
+import { OpenFeature, InMemoryProvider } from '../../src';
+import flagConfiguration from './flags-config';
 // load the feature file.
 const feature = loadFeature('packages/server/e2e/features/evaluation.feature');
 
@@ -18,7 +19,9 @@ const client = OpenFeature.getClient();
 const givenAnOpenfeatureClientIsRegisteredWithCacheDisabled = (
   given: (stepMatcher: string, stepDefinitionCallback: () => void) => void
 ) => {
-  // TODO: when the FlagdProvider is updated to support caching, we may need to disable it here for this test to work as expected.
+  OpenFeature.setProvider(
+    new InMemoryProvider(flagConfiguration),
+  );
   given('a provider is registered with cache disabled', () => undefined);
 };
 
diff --git a/packages/server/e2e/step-definitions/flags-config.ts b/packages/server/e2e/step-definitions/flags-config.ts
new file mode 100644
index 00000000..17956b13
--- /dev/null
+++ b/packages/server/e2e/step-definitions/flags-config.ts
@@ -0,0 +1,71 @@
+export default {
+  'boolean-flag': {
+    disabled: false,
+    variants: {
+      on: true,
+      off: false,
+    },
+    defaultVariant: 'on',
+  },
+  'string-flag': {
+    disabled: false,
+    variants: {
+      greeting: 'hi',
+      parting: 'bye',
+    },
+    defaultVariant: 'greeting',
+  },
+  'integer-flag': {
+    disabled: false,
+    variants: {
+      one: 1,
+      ten: 10,
+    },
+    defaultVariant: 'ten',
+  },
+  'float-flag': {
+    disabled: false,
+    variants: {
+      tenth: 0.1,
+      half: 0.5,
+    },
+    defaultVariant: 'half',
+  },
+  'object-flag': {
+    disabled: false,
+    variants: {
+      empty: {},
+      template: {
+        showImages: true,
+        title: 'Check out these pics!',
+        imagesPerPage: 100,
+      },
+    },
+    defaultVariant: 'template',
+  },
+  'context-aware': {
+    disabled: false,
+    variants: {
+      internal: 'INTERNAL',
+      external: 'EXTERNAL',
+    },
+    defaultVariant: 'external',
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    contextEvaluator(ctx: any) {
+      const { fn, ln, age, customer } = ctx;
+      if (fn === 'Sulisław' && ln === 'Świętopełk' && age === 29 && customer === false) {
+        return 'internal';
+      } else {
+        return 'external';
+      }
+    },
+  },
+  'wrong-flag': {
+    disabled: false,
+    variants: {
+      one: 'uno',
+      two: 'dos',
+    },
+    defaultVariant: 'one',
+  },
+};
diff --git a/packages/server/e2e/step-definitions/jest.config.ts b/packages/server/e2e/step-definitions/jest.config.ts
deleted file mode 100644
index c56a4ed0..00000000
--- a/packages/server/e2e/step-definitions/jest.config.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export default {
-  clearMocks: true,
-  collectCoverage: true,
-  coverageDirectory: 'coverage',
-  coverageProvider: 'v8',
-  globals: {
-    'ts-jest': {
-      tsConfig: 'e2e/step-definitions/tsconfig.json',
-    },
-  },
-  moduleNameMapper: {
-    '^(.*)\\.js$': ['$1', '$1.js'],
-  },
-  setupFiles: ['./setup.ts'],
-  preset: 'ts-jest',
-};
diff --git a/packages/server/e2e/step-definitions/setup.ts b/packages/server/e2e/step-definitions/setup.ts
deleted file mode 100644
index 850b598e..00000000
--- a/packages/server/e2e/step-definitions/setup.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import assert from 'assert';
-import { OpenFeature } from '../..';
-import { FlagdProvider } from '@openfeature/flagd-provider';
-
-const FLAGD_NAME = 'flagd Provider';
-
-// register the flagd provider before the tests.
-console.log('Setting flagd provider...');
-OpenFeature.setProvider(new FlagdProvider({ cache: 'disabled' }));
-assert(
-  OpenFeature.providerMetadata.name === FLAGD_NAME,
-  new Error(`Expected ${FLAGD_NAME} provider to be configured, instead got: ${OpenFeature.providerMetadata.name}`)
-);
-console.log('flagd provider configured!');