add cache testing utilities
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -25,6 +25,7 @@ import { HttpRouterFactoryOptions } from '@backstage/backend-app-api';
|
||||
import { HttpRouterService } from '@backstage/backend-plugin-api';
|
||||
import { IdentityService } from '@backstage/backend-plugin-api';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import Keyv from 'keyv';
|
||||
import { Knex } from 'knex';
|
||||
import { LifecycleService } from '@backstage/backend-plugin-api';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
@@ -423,6 +424,28 @@ export interface TestBackendOptions<TExtensionPoints extends any[]> {
|
||||
>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type TestCacheId = 'MEMORY' | 'REDIS_7' | 'MEMCACHED_1';
|
||||
|
||||
// @public
|
||||
export class TestCaches {
|
||||
static create(options?: {
|
||||
ids?: TestCacheId[];
|
||||
disableDocker?: boolean;
|
||||
}): TestCaches;
|
||||
// (undocumented)
|
||||
eachSupportedId(): [TestCacheId][];
|
||||
init(id: TestCacheId): Promise<{
|
||||
store: string;
|
||||
connection: string;
|
||||
keyv: Keyv;
|
||||
}>;
|
||||
// (undocumented)
|
||||
static setDefaults(options: { ids?: TestCacheId[] }): void;
|
||||
// (undocumented)
|
||||
supports(id: TestCacheId): boolean;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type TestDatabaseId =
|
||||
| 'POSTGRES_16'
|
||||
|
||||
@@ -53,10 +53,14 @@
|
||||
"@backstage/plugin-auth-node": "workspace:^",
|
||||
"@backstage/plugin-events-node": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@keyv/memcache": "^1.3.5",
|
||||
"@keyv/redis": "^2.5.3",
|
||||
"@types/keyv": "^4.2.0",
|
||||
"better-sqlite3": "^9.0.0",
|
||||
"cookie": "^0.6.0",
|
||||
"express": "^4.17.1",
|
||||
"fs-extra": "^11.0.0",
|
||||
"keyv": "^4.5.2",
|
||||
"knex": "^3.0.0",
|
||||
"msw": "^1.0.0",
|
||||
"mysql2": "^3.0.0",
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isDockerDisabledForTests } from '../util';
|
||||
import { TestCaches } from './TestCaches';
|
||||
|
||||
const itIfDocker = isDockerDisabledForTests() ? it.skip : it;
|
||||
|
||||
jest.setTimeout(60_000);
|
||||
|
||||
describe('TestCaches', () => {
|
||||
const caches = TestCaches.create();
|
||||
|
||||
it.each(caches.eachSupportedId())('fires up a cache, %p', async cacheId => {
|
||||
const { keyv } = await caches.init(cacheId);
|
||||
await keyv.set('test', 'value');
|
||||
await expect(keyv.get('test')).resolves.toBe('value');
|
||||
});
|
||||
|
||||
itIfDocker('clears between tests, part 1', async () => {
|
||||
const { keyv } = await caches.init('REDIS_7');
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
await expect(keyv.get('collision')).resolves.toBeUndefined();
|
||||
await keyv.set('collision', 'something');
|
||||
});
|
||||
|
||||
itIfDocker('clears between tests, part 2', async () => {
|
||||
const { keyv } = await caches.init('REDIS_7');
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
await expect(keyv.get('collision')).resolves.toBeUndefined();
|
||||
await keyv.set('collision', 'something');
|
||||
});
|
||||
|
||||
itIfDocker('clears between tests, part 3', async () => {
|
||||
const { keyv } = await caches.init('REDIS_7');
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
await expect(keyv.get('collision')).resolves.toBeUndefined();
|
||||
await keyv.set('collision', 'something');
|
||||
});
|
||||
});
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Keyv from 'keyv';
|
||||
import { isDockerDisabledForTests } from '../util/isDockerDisabledForTests';
|
||||
import { connectToExternalMemcache, startMemcachedContainer } from './memcache';
|
||||
import { connectToExternalRedis, startRedisContainer } from './redis';
|
||||
import { Instance, TestCacheId, TestCacheProperties, allCaches } from './types';
|
||||
|
||||
/**
|
||||
* Encapsulates the creation of ephemeral test cache instances for use inside
|
||||
* unit or integration tests.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class TestCaches {
|
||||
private readonly instanceById: Map<string, Instance>;
|
||||
private readonly supportedIds: TestCacheId[];
|
||||
private static defaultIds?: TestCacheId[];
|
||||
|
||||
/**
|
||||
* Creates an empty `TestCaches` instance, and sets up Jest to clean up all of
|
||||
* its acquired resources after all tests finish.
|
||||
*
|
||||
* You typically want to create just a single instance like this at the top of
|
||||
* your test file or `describe` block, and then call `init` many times on that
|
||||
* instance inside the individual tests. Spinning up a "physical" cache
|
||||
* instance takes a considerable amount of time, slowing down tests. But
|
||||
* wiping the contents of an instance using `init` is very fast.
|
||||
*/
|
||||
static create(options?: {
|
||||
ids?: TestCacheId[];
|
||||
disableDocker?: boolean;
|
||||
}): TestCaches {
|
||||
const ids = options?.ids;
|
||||
const disableDocker = options?.disableDocker ?? isDockerDisabledForTests();
|
||||
|
||||
let testCacheIds: TestCacheId[];
|
||||
if (ids) {
|
||||
testCacheIds = ids;
|
||||
} else if (TestCaches.defaultIds) {
|
||||
testCacheIds = TestCaches.defaultIds;
|
||||
} else {
|
||||
testCacheIds = Object.keys(allCaches) as TestCacheId[];
|
||||
}
|
||||
|
||||
const supportedIds = testCacheIds.filter(id => {
|
||||
const properties = allCaches[id];
|
||||
if (!properties) {
|
||||
return false;
|
||||
}
|
||||
// If the caller has set up the env with an explicit connection string,
|
||||
// we'll assume that this target will work
|
||||
if (
|
||||
properties.connectionStringEnvironmentVariableName &&
|
||||
process.env[properties.connectionStringEnvironmentVariableName]
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
// If the cache doesn't require docker at all, there's nothing to worry
|
||||
// about
|
||||
if (!properties.dockerImageName) {
|
||||
return true;
|
||||
}
|
||||
// If the cache requires docker, but docker is disabled, we will fail.
|
||||
if (disableDocker) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const caches = new TestCaches(supportedIds);
|
||||
|
||||
if (supportedIds.length > 0) {
|
||||
afterAll(async () => {
|
||||
await caches.shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
return caches;
|
||||
}
|
||||
|
||||
static setDefaults(options: { ids?: TestCacheId[] }) {
|
||||
TestCaches.defaultIds = options.ids;
|
||||
}
|
||||
|
||||
private constructor(supportedIds: TestCacheId[]) {
|
||||
this.instanceById = new Map();
|
||||
this.supportedIds = supportedIds;
|
||||
}
|
||||
|
||||
supports(id: TestCacheId): boolean {
|
||||
return this.supportedIds.includes(id);
|
||||
}
|
||||
|
||||
eachSupportedId(): [TestCacheId][] {
|
||||
return this.supportedIds.map(id => [id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fresh, empty cache for the given driver.
|
||||
*
|
||||
* @param id - The ID of the cache to use, e.g. 'REDIS_7'
|
||||
* @returns Cache connection properties
|
||||
*/
|
||||
async init(
|
||||
id: TestCacheId,
|
||||
): Promise<{ store: string; connection: string; keyv: Keyv }> {
|
||||
const properties = allCaches[id];
|
||||
if (!properties) {
|
||||
const candidates = Object.keys(allCaches).join(', ');
|
||||
throw new Error(
|
||||
`Unknown test cache ${id}, possible values are ${candidates}`,
|
||||
);
|
||||
}
|
||||
if (!this.supportedIds.includes(id)) {
|
||||
const candidates = this.supportedIds.join(', ');
|
||||
throw new Error(
|
||||
`Unsupported test cache ${id} for this environment, possible values are ${candidates}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure that a testcontainers instance is up for this ID
|
||||
let instance: Instance | undefined = this.instanceById.get(id);
|
||||
if (!instance) {
|
||||
instance = await this.initAny(properties);
|
||||
this.instanceById.set(id, instance);
|
||||
}
|
||||
|
||||
// Ensure that it's cleared of data from previous tests
|
||||
await instance.keyv.clear();
|
||||
|
||||
return {
|
||||
store: instance.store,
|
||||
connection: instance.connection,
|
||||
keyv: instance.keyv,
|
||||
};
|
||||
}
|
||||
|
||||
private async initAny(properties: TestCacheProperties): Promise<Instance> {
|
||||
switch (properties.store) {
|
||||
case 'memcache':
|
||||
return this.initMemcached(properties);
|
||||
case 'redis':
|
||||
return this.initRedis(properties);
|
||||
case 'memory':
|
||||
return {
|
||||
store: 'memory',
|
||||
connection: 'memory',
|
||||
keyv: new Keyv(),
|
||||
stop: async () => {},
|
||||
};
|
||||
default:
|
||||
throw new Error(`Unknown cache store '${properties.store}'`);
|
||||
}
|
||||
}
|
||||
|
||||
private async initMemcached(
|
||||
properties: TestCacheProperties,
|
||||
): Promise<Instance> {
|
||||
// Use the connection string if provided
|
||||
const envVarName = properties.connectionStringEnvironmentVariableName;
|
||||
if (envVarName) {
|
||||
const connectionString = process.env[envVarName];
|
||||
if (connectionString) {
|
||||
return connectToExternalMemcache(connectionString);
|
||||
}
|
||||
}
|
||||
|
||||
return await startMemcachedContainer(properties.dockerImageName!);
|
||||
}
|
||||
|
||||
private async initRedis(properties: TestCacheProperties): Promise<Instance> {
|
||||
// Use the connection string if provided
|
||||
const envVarName = properties.connectionStringEnvironmentVariableName;
|
||||
if (envVarName) {
|
||||
const connectionString = process.env[envVarName];
|
||||
if (connectionString) {
|
||||
return connectToExternalRedis(connectionString);
|
||||
}
|
||||
}
|
||||
|
||||
return await startRedisContainer(properties.dockerImageName!);
|
||||
}
|
||||
|
||||
private async shutdown() {
|
||||
const instances = [...this.instanceById.values()];
|
||||
this.instanceById.clear();
|
||||
await Promise.all(
|
||||
instances.map(({ stop }) =>
|
||||
stop().catch(error => {
|
||||
console.warn(`TestCaches: Failed to stop container`, { error });
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { TestCaches } from './TestCaches';
|
||||
export type { TestCacheId } from './types';
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isDockerDisabledForTests } from '../util/isDockerDisabledForTests';
|
||||
import { startMemcachedContainer } from './memcache';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const itIfDocker = isDockerDisabledForTests() ? it.skip : it;
|
||||
|
||||
jest.setTimeout(60_000);
|
||||
|
||||
describe('startMemcachedContainer', () => {
|
||||
itIfDocker('successfully launches the container', async () => {
|
||||
const { stop, keyv } = await startMemcachedContainer('memcached:1');
|
||||
const value = uuid();
|
||||
await keyv.set('test', value);
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
await expect(keyv.get('test')).resolves.toBe(value);
|
||||
await stop();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Keyv from 'keyv';
|
||||
import KeyvMemcache from '@keyv/memcache';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Instance } from './types';
|
||||
|
||||
async function attemptMemcachedConnection(connection: string): Promise<Keyv> {
|
||||
const startTime = Date.now();
|
||||
|
||||
for (;;) {
|
||||
try {
|
||||
const store = new KeyvMemcache(connection);
|
||||
const keyv = new Keyv({ store });
|
||||
const value = uuid();
|
||||
await keyv.set('test', value);
|
||||
if ((await keyv.get('test')) === value) {
|
||||
return keyv;
|
||||
}
|
||||
} catch (e) {
|
||||
if (Date.now() - startTime > 30_000) {
|
||||
throw new Error(
|
||||
`Timed out waiting for memcached to be ready for connections, ${e}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectToExternalMemcache(
|
||||
connection: string,
|
||||
): Promise<Instance> {
|
||||
const keyv = await attemptMemcachedConnection(connection);
|
||||
return {
|
||||
store: 'memcache',
|
||||
connection,
|
||||
keyv,
|
||||
stop: async () => await keyv.disconnect(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function startMemcachedContainer(
|
||||
image: string,
|
||||
): Promise<Instance> {
|
||||
// Lazy-load to avoid side-effect of importing testcontainers
|
||||
const { GenericContainer } = await import('testcontainers');
|
||||
|
||||
const container = await new GenericContainer(image)
|
||||
.withExposedPorts(11211)
|
||||
.start();
|
||||
|
||||
const host = container.getHost();
|
||||
const port = container.getMappedPort(11211);
|
||||
const connection = `${host}:${port}`;
|
||||
|
||||
const keyv = await attemptMemcachedConnection(connection);
|
||||
|
||||
return {
|
||||
store: 'memcache',
|
||||
connection,
|
||||
keyv,
|
||||
stop: async () => {
|
||||
await keyv.disconnect();
|
||||
await container.stop({ timeout: 10_000 });
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isDockerDisabledForTests } from '../util/isDockerDisabledForTests';
|
||||
import { startRedisContainer } from './redis';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const itIfDocker = isDockerDisabledForTests() ? it.skip : it;
|
||||
|
||||
jest.setTimeout(60_000);
|
||||
|
||||
describe('startRedisContainer', () => {
|
||||
itIfDocker('successfully launches the container', async () => {
|
||||
const { stop, keyv } = await startRedisContainer('redis:7');
|
||||
const value = uuid();
|
||||
await keyv.set('test', value);
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
await expect(keyv.get('test')).resolves.toBe(value);
|
||||
await stop();
|
||||
});
|
||||
});
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Keyv from 'keyv';
|
||||
import KeyvRedis from '@keyv/redis';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Instance } from './types';
|
||||
|
||||
async function attemptRedisConnection(connection: string): Promise<Keyv> {
|
||||
const startTime = Date.now();
|
||||
|
||||
for (;;) {
|
||||
try {
|
||||
const store = new KeyvRedis(connection);
|
||||
const keyv = new Keyv({ store });
|
||||
const value = uuid();
|
||||
await keyv.set('test', value);
|
||||
if ((await keyv.get('test')) === value) {
|
||||
return keyv;
|
||||
}
|
||||
} catch (e) {
|
||||
if (Date.now() - startTime > 30_000) {
|
||||
throw new Error(
|
||||
`Timed out waiting for redis to be ready for connections, ${e}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
}
|
||||
|
||||
export async function connectToExternalRedis(
|
||||
connection: string,
|
||||
): Promise<Instance> {
|
||||
const keyv = await attemptRedisConnection(connection);
|
||||
return {
|
||||
store: 'redis',
|
||||
connection,
|
||||
keyv,
|
||||
stop: async () => await keyv.disconnect(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function startRedisContainer(image: string): Promise<Instance> {
|
||||
// Lazy-load to avoid side-effect of importing testcontainers
|
||||
const { GenericContainer } = await import('testcontainers');
|
||||
|
||||
const container = await new GenericContainer(image)
|
||||
.withExposedPorts(6379)
|
||||
.start();
|
||||
|
||||
const host = container.getHost();
|
||||
const port = container.getMappedPort(6379);
|
||||
const connection = `redis://${host}:${port}`;
|
||||
|
||||
const keyv = await attemptRedisConnection(connection);
|
||||
|
||||
return {
|
||||
store: 'redis',
|
||||
connection,
|
||||
keyv,
|
||||
stop: async () => {
|
||||
await keyv.disconnect();
|
||||
await container.stop({ timeout: 10_000 });
|
||||
},
|
||||
};
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Keyv from 'keyv';
|
||||
import { getDockerImageForName } from '../util/getDockerImageForName';
|
||||
|
||||
/**
|
||||
* The possible caches to test against.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TestCacheId = 'MEMORY' | 'REDIS_7' | 'MEMCACHED_1';
|
||||
|
||||
export type TestCacheProperties = {
|
||||
name: string;
|
||||
store: string;
|
||||
dockerImageName?: string;
|
||||
connectionStringEnvironmentVariableName?: string;
|
||||
};
|
||||
|
||||
export type Instance = {
|
||||
store: string;
|
||||
connection: string;
|
||||
keyv: Keyv;
|
||||
stop: () => Promise<void>;
|
||||
};
|
||||
|
||||
export const allCaches: Record<TestCacheId, TestCacheProperties> =
|
||||
Object.freeze({
|
||||
REDIS_7: {
|
||||
name: 'Redis 7.x',
|
||||
store: 'redis',
|
||||
dockerImageName: getDockerImageForName('redis:7'),
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_CACHE_REDIS7_CONNECTION_STRING',
|
||||
},
|
||||
MEMCACHED_1: {
|
||||
name: 'Memcached 1.x',
|
||||
store: 'memcache',
|
||||
dockerImageName: getDockerImageForName('memcached:1'),
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_CACHE_MEMCACHED1_CONNECTION_STRING',
|
||||
},
|
||||
MEMORY: {
|
||||
name: 'In-memory',
|
||||
store: 'memory',
|
||||
},
|
||||
});
|
||||
@@ -14,6 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { isDockerDisabledForTests } from '../util/isDockerDisabledForTests';
|
||||
export { TestDatabases } from './TestDatabases';
|
||||
export type { TestDatabaseId } from './types';
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './cache';
|
||||
export * from './database';
|
||||
export * from './msw';
|
||||
export * from './filesystem';
|
||||
|
||||
@@ -20,7 +20,7 @@ export function isDockerDisabledForTests() {
|
||||
// the (relatively heavy, long running) docker based tests. If you want to
|
||||
// still run local tests for all databases, just pass either the CI=1 env
|
||||
// parameter to your test runner, or individual connection strings per
|
||||
// database.
|
||||
// database or cache.
|
||||
return (
|
||||
Boolean(process.env.BACKSTAGE_TEST_DISABLE_DOCKER) ||
|
||||
!Boolean(process.env.CI)
|
||||
|
||||
Reference in New Issue
Block a user