Skip to content

Commit

Permalink
Use jest.spyOn instead of delegate object in with-cache
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrisbin committed Feb 13, 2024
1 parent f76616d commit bb5e7c1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 56 deletions.
52 changes: 22 additions & 30 deletions src/with-cache.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import * as core from "@actions/core";
import * as cache from "@actions/cache";

import { getCacheKeys } from "./get-cache-keys";
import { DEFAULT_CACHE_OPTIONS, withCache } from "./with-cache";

const core = {
info: jest.fn(),
};

const cache = {
restoreCache: jest.fn(),
saveCache: jest.fn(),
};

const TEST_CACHE_OPTIONS = {
...DEFAULT_CACHE_OPTIONS,
coreDelegate: core,
cacheDelegate: cache,
};
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
jest.spyOn(cache, "saveCache");
jest.spyOn(core, "info");

async function testFunction(): Promise<number> {
return 42;
Expand All @@ -27,29 +19,29 @@ async function testFunctionThrows(): Promise<number> {
function simulateCacheHit(
_paths: string[],
primaryKey: string,
_restoreKeys: string[],
): string {
return primaryKey;
_restoreKeys?: string[],
): Promise<string | undefined> {
return Promise.resolve(primaryKey);
}

function simulateCacheMiss(
_paths: string[],
primaryKey: string,
_restoreKeys: string[],
): string {
return primaryKey.replace(/-*$/, "-XXX");
_restoreKeys?: string[],
): Promise<string | undefined> {
return Promise.resolve(primaryKey.replace(/-*$/, "-XXX"));
}

test("withCache skips on primary-key hit", async () => {
const cachePaths = ["/a", "/b"];
const cacheKeys = getCacheKeys(["a-b", "c", "d"]);
cache.restoreCache.mockImplementation(simulateCacheHit);
restoreCacheMock.mockImplementation(simulateCacheHit);

const result = await withCache(
cachePaths,
cacheKeys,
testFunction,
TEST_CACHE_OPTIONS,
DEFAULT_CACHE_OPTIONS,
);

expect(result).toBeUndefined();
Expand All @@ -64,13 +56,13 @@ test("withCache skips on primary-key hit", async () => {
test("withCache acts and saves if no primary-key hit", async () => {
const cachePaths = ["/a", "/b"];
const cacheKeys = getCacheKeys(["a-b", "c", "d"]);
cache.restoreCache.mockImplementation(simulateCacheMiss);
restoreCacheMock.mockImplementation(simulateCacheMiss);

const result = await withCache(
cachePaths,
cacheKeys,
testFunction,
TEST_CACHE_OPTIONS,
DEFAULT_CACHE_OPTIONS,
);

expect(result).toEqual(42);
Expand All @@ -88,10 +80,10 @@ test("withCache acts and saves if no primary-key hit", async () => {
test("withCache can be configured to act and save anyway", async () => {
const cachePaths = ["/a", "/b"];
const cacheKeys = getCacheKeys(["a-b", "c", "d"]);
cache.restoreCache.mockImplementation(simulateCacheHit);
restoreCacheMock.mockImplementation(simulateCacheHit);

const result = await withCache(cachePaths, cacheKeys, testFunction, {
...TEST_CACHE_OPTIONS,
...DEFAULT_CACHE_OPTIONS,
skipOnHit: false,
});

Expand All @@ -109,14 +101,14 @@ test("withCache can be configured to act and save anyway", async () => {
test("withCache does not save on error", async () => {
const cachePaths = ["/a", "/b"];
const cacheKeys = getCacheKeys(["a-b", "c", "d"]);
cache.restoreCache.mockImplementation(simulateCacheMiss);
restoreCacheMock.mockImplementation(simulateCacheMiss);

await expect(async () => {
await withCache(
cachePaths,
cacheKeys,
testFunctionThrows,
TEST_CACHE_OPTIONS,
DEFAULT_CACHE_OPTIONS,
);
}).rejects.toThrow();

Expand All @@ -133,11 +125,11 @@ test("withCache does not save on error", async () => {
test("withCache can be configured to save on error", async () => {
const cachePaths = ["/a", "/b"];
const cacheKeys = getCacheKeys(["a-b", "c", "d"]);
cache.restoreCache.mockImplementation(simulateCacheMiss);
restoreCacheMock.mockImplementation(simulateCacheMiss);

await expect(async () => {
await withCache(cachePaths, cacheKeys, testFunctionThrows, {
...TEST_CACHE_OPTIONS,
...DEFAULT_CACHE_OPTIONS,
saveOnError: true,
});
}).rejects.toThrow();
Expand Down
35 changes: 9 additions & 26 deletions src/with-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,14 @@ import * as core from "@actions/core";
import * as cache from "@actions/cache";
import type { CacheKeys } from "./get-cache-keys";

export interface CoreDelegate {
info: (msg: string) => void;
}

export interface CacheDelegate {
restoreCache: (
paths: string[],
primaryKey: string,
restoreKeys: string[],
) => Promise<string | undefined>;
saveCache: (paths: string[], primaryKey: string) => Promise<number>;
}

export type CacheOptions = {
skipOnHit: boolean;
saveOnError: boolean;
coreDelegate: CoreDelegate;
cacheDelegate: CacheDelegate;
};

export const DEFAULT_CACHE_OPTIONS = {
skipOnHit: true,
saveOnError: false,
coreDelegate: core,
cacheDelegate: cache,
};

export async function withCache<T>(
Expand All @@ -35,23 +18,23 @@ export async function withCache<T>(
fn: () => Promise<T>,
options: CacheOptions = DEFAULT_CACHE_OPTIONS,
): Promise<T | undefined> {
const { skipOnHit, saveOnError, coreDelegate, cacheDelegate } = options;
const { skipOnHit, saveOnError } = options;

coreDelegate.info(`Paths:\n - ${paths.join("\n - ")}`);
coreDelegate.info(`Primary key: ${keys.primaryKey}`);
coreDelegate.info(`Restore keys:\n - ${keys.restoreKeys.join("\n - ")}`);
core.info(`Paths:\n - ${paths.join("\n - ")}`);
core.info(`Primary key: ${keys.primaryKey}`);
core.info(`Restore keys:\n - ${keys.restoreKeys.join("\n - ")}`);

const restoredKey = await cacheDelegate.restoreCache(
const restoredKey = await cache.restoreCache(
paths,
keys.primaryKey,
keys.restoreKeys,
);

const primaryKeyHit = restoredKey == keys.primaryKey;
coreDelegate.info(`Restored key: ${restoredKey ?? "<none>"}`);
core.info(`Restored key: ${restoredKey ?? "<none>"}`);

if (primaryKeyHit && skipOnHit && !saveOnError) {
coreDelegate.info("Skipping due to primary key hit");
core.info("Skipping due to primary key hit");
return;
}

Expand All @@ -61,11 +44,11 @@ export async function withCache<T>(
result = await fn();

if (!primaryKeyHit) {
await cacheDelegate.saveCache(paths, keys.primaryKey);
await cache.saveCache(paths, keys.primaryKey);
}
} catch (ex) {
if (saveOnError && !primaryKeyHit) {
await cacheDelegate.saveCache(paths, keys.primaryKey);
await cache.saveCache(paths, keys.primaryKey);
}

throw ex;
Expand Down

0 comments on commit bb5e7c1

Please sign in to comment.