|
@@ -1,7 +1,7 @@
|
|
|
-import { CacheService, Logger, mergeConfig, RedisCachePlugin } from '@vendure/core';
|
|
|
|
|
|
|
+import { CacheService, mergeConfig, RedisCachePlugin } from '@vendure/core';
|
|
|
import { createTestEnvironment } from '@vendure/testing';
|
|
import { createTestEnvironment } from '@vendure/testing';
|
|
|
import path from 'path';
|
|
import path from 'path';
|
|
|
-import { vi, afterAll, beforeAll, describe, it, expect } from 'vitest';
|
|
|
|
|
|
|
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
|
|
|
|
|
|
import { initialData } from '../../../e2e-common/e2e-initial-data';
|
|
import { initialData } from '../../../e2e-common/e2e-initial-data';
|
|
|
import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
|
|
import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
|
|
@@ -15,86 +15,120 @@ import {
|
|
|
invalidatesManyByMultipleTags,
|
|
invalidatesManyByMultipleTags,
|
|
|
invalidTTLsShouldNotSetKey,
|
|
invalidTTLsShouldNotSetKey,
|
|
|
setsAKey,
|
|
setsAKey,
|
|
|
- setsAKeyWithSubSecondTtl,
|
|
|
|
|
- setsAKeyWithTtl,
|
|
|
|
|
setsArrayOfObjects,
|
|
setsArrayOfObjects,
|
|
|
setsArrayValue,
|
|
setsArrayValue,
|
|
|
setsObjectValue,
|
|
setsObjectValue,
|
|
|
} from './fixtures/cache-service-shared-tests';
|
|
} from './fixtures/cache-service-shared-tests';
|
|
|
|
|
|
|
|
-describe('CacheService with RedisCachePlugin', () => {
|
|
|
|
|
- let cacheService: CacheService;
|
|
|
|
|
- const { server, adminClient } = createTestEnvironment(
|
|
|
|
|
- mergeConfig(testConfig(), {
|
|
|
|
|
- plugins: [
|
|
|
|
|
- RedisCachePlugin.init({
|
|
|
|
|
- redisOptions: {
|
|
|
|
|
- host: '127.0.0.1',
|
|
|
|
|
- port: process.env.CI ? +(process.env.E2E_REDIS_PORT || 6379) : 6379,
|
|
|
|
|
- },
|
|
|
|
|
- }),
|
|
|
|
|
- ],
|
|
|
|
|
- }),
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- beforeAll(async () => {
|
|
|
|
|
- await server.init({
|
|
|
|
|
- initialData,
|
|
|
|
|
- productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
|
|
|
|
|
- customerCount: 1,
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Checks if Redis is available at the specified host and port
|
|
|
|
|
+ */
|
|
|
|
|
+async function isRedisAvailable(host: string, port: number): Promise<boolean> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const IORedis = await import('ioredis').then(m => m.default);
|
|
|
|
|
+ const testClient = new IORedis.Redis({
|
|
|
|
|
+ host,
|
|
|
|
|
+ port,
|
|
|
|
|
+ connectTimeout: 2000,
|
|
|
|
|
+ lazyConnect: true,
|
|
|
|
|
+ maxRetriesPerRequest: 1,
|
|
|
});
|
|
});
|
|
|
- await adminClient.asSuperAdmin();
|
|
|
|
|
- cacheService = server.app.get(CacheService);
|
|
|
|
|
- }, TEST_SETUP_TIMEOUT_MS);
|
|
|
|
|
|
|
|
|
|
- afterAll(async () => {
|
|
|
|
|
- await server.destroy();
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ await testClient.ping();
|
|
|
|
|
+ await testClient.quit();
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const redisHost = '127.0.0.1';
|
|
|
|
|
+const redisPort = process.env.CI ? +(process.env.E2E_REDIS_PORT || 6379) : 6379;
|
|
|
|
|
+
|
|
|
|
|
+describe('CacheService with RedisCachePlugin', async () => {
|
|
|
|
|
+ const redisAvailable = await isRedisAvailable(redisHost, redisPort);
|
|
|
|
|
+
|
|
|
|
|
+ if (!redisAvailable) {
|
|
|
|
|
+ // eslint-disable-next-line no-console
|
|
|
|
|
+ console.warn(`Redis server not available at ${redisHost}:${redisPort}. Skipping Redis cache tests.`);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ describe.skipIf(!redisAvailable)('Redis Cache Tests', () => {
|
|
|
|
|
+ let cacheService: CacheService;
|
|
|
|
|
+
|
|
|
|
|
+ const { server, adminClient } = createTestEnvironment(
|
|
|
|
|
+ mergeConfig(testConfig(), {
|
|
|
|
|
+ plugins: [
|
|
|
|
|
+ RedisCachePlugin.init({
|
|
|
|
|
+ redisOptions: {
|
|
|
|
|
+ host: redisHost,
|
|
|
|
|
+ port: redisPort,
|
|
|
|
|
+ },
|
|
|
|
|
+ }),
|
|
|
|
|
+ ],
|
|
|
|
|
+ }),
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ beforeAll(async () => {
|
|
|
|
|
+ await server.init({
|
|
|
|
|
+ initialData,
|
|
|
|
|
+ productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
|
|
|
|
|
+ customerCount: 1,
|
|
|
|
|
+ });
|
|
|
|
|
+ await adminClient.asSuperAdmin();
|
|
|
|
|
+ cacheService = server.app.get(CacheService);
|
|
|
|
|
+ }, TEST_SETUP_TIMEOUT_MS);
|
|
|
|
|
+
|
|
|
|
|
+ afterAll(async () => {
|
|
|
|
|
+ await server.destroy();
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- it('get returns undefined for non-existent key', () =>
|
|
|
|
|
- getReturnsUndefinedForNonExistentKey(cacheService));
|
|
|
|
|
|
|
+ it('get returns undefined for non-existent key', () =>
|
|
|
|
|
+ getReturnsUndefinedForNonExistentKey(cacheService));
|
|
|
|
|
|
|
|
- it('sets a key', () => setsAKey(cacheService));
|
|
|
|
|
|
|
+ it('sets a key', () => setsAKey(cacheService));
|
|
|
|
|
|
|
|
- it('sets an object value', () => setsObjectValue(cacheService));
|
|
|
|
|
|
|
+ it('sets an object value', () => setsObjectValue(cacheService));
|
|
|
|
|
|
|
|
- it('sets an array value', () => setsArrayValue(cacheService));
|
|
|
|
|
|
|
+ it('sets an array value', () => setsArrayValue(cacheService));
|
|
|
|
|
|
|
|
- it('sets an array of objects', () => setsArrayOfObjects(cacheService));
|
|
|
|
|
|
|
+ it('sets an array of objects', () => setsArrayOfObjects(cacheService));
|
|
|
|
|
|
|
|
- it('deletes a key', () => deletesAKey(cacheService));
|
|
|
|
|
|
|
+ it('deletes a key', () => deletesAKey(cacheService));
|
|
|
|
|
|
|
|
- it('sets a key with ttl', async () => {
|
|
|
|
|
- await cacheService.set('test-key1', 'test-value', { ttl: 1000 });
|
|
|
|
|
- const result = await cacheService.get('test-key1');
|
|
|
|
|
- expect(result).toBe('test-value');
|
|
|
|
|
|
|
+ it('sets a key with ttl', async () => {
|
|
|
|
|
+ await cacheService.set('test-key1', 'test-value', { ttl: 1000 });
|
|
|
|
|
+ const result = await cacheService.get('test-key1');
|
|
|
|
|
+ expect(result).toBe('test-value');
|
|
|
|
|
|
|
|
- await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
|
|
|
|
- const result2 = await cacheService.get('test-key1');
|
|
|
|
|
|
|
+ const result2 = await cacheService.get('test-key1');
|
|
|
|
|
|
|
|
- expect(result2).toBeUndefined();
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ expect(result2).toBeUndefined();
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- it('sets a key with sub-second ttl', async () => {
|
|
|
|
|
- await cacheService.set('test-key2', 'test-value', { ttl: 900 });
|
|
|
|
|
- const result = await cacheService.get('test-key2');
|
|
|
|
|
- expect(result).toBe('test-value');
|
|
|
|
|
|
|
+ it('sets a key with sub-second ttl', async () => {
|
|
|
|
|
+ await cacheService.set('test-key2', 'test-value', { ttl: 900 });
|
|
|
|
|
+ const result = await cacheService.get('test-key2');
|
|
|
|
|
+ expect(result).toBe('test-value');
|
|
|
|
|
|
|
|
- await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
|
|
|
|
- const result2 = await cacheService.get('test-key2');
|
|
|
|
|
|
|
+ const result2 = await cacheService.get('test-key2');
|
|
|
|
|
|
|
|
- expect(result2).toBeUndefined();
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ expect(result2).toBeUndefined();
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- it('invalidates by single tag', () => invalidatesBySingleTag(cacheService));
|
|
|
|
|
|
|
+ it('invalidates by single tag', () => invalidatesBySingleTag(cacheService));
|
|
|
|
|
|
|
|
- it('invalidates by multiple tags', () => invalidatesByMultipleTags(cacheService));
|
|
|
|
|
|
|
+ it('invalidates by multiple tags', () => invalidatesByMultipleTags(cacheService));
|
|
|
|
|
|
|
|
- it('invalidates many by multiple tags', () => invalidatesManyByMultipleTags(cacheService));
|
|
|
|
|
|
|
+ it('invalidates many by multiple tags', () => invalidatesManyByMultipleTags(cacheService));
|
|
|
|
|
|
|
|
- it('invalidates a large number of keys by tag', () => invalidatesALargeNumberOfKeysByTag(cacheService));
|
|
|
|
|
|
|
+ it('invalidates a large number of keys by tag', () =>
|
|
|
|
|
+ invalidatesALargeNumberOfKeysByTag(cacheService));
|
|
|
|
|
|
|
|
- it('invalid ttls should not set key', () => invalidTTLsShouldNotSetKey(cacheService));
|
|
|
|
|
|
|
+ it('invalid ttls should not set key', () => invalidTTLsShouldNotSetKey(cacheService));
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|