mirror of
				https://github.com/actions/cache.git
				synced 2025-11-04 15:48:39 +08:00 
			
		
		
		
	Add tests for cache refreshing.
This commit is contained in:
		
							parent
							
								
									39c1f23499
								
							
						
					
					
						commit
						34ae092a8c
					
				| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import { RequestError } from "@octokit/request-error";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, RefKey } from "../src/constants";
 | 
			
		||||
import * as actionUtils from "../src/utils/actionUtils";
 | 
			
		||||
| 
						 | 
				
			
			@ -12,9 +14,13 @@ let pristineEnv: NodeJS.ProcessEnv;
 | 
			
		|||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    pristineEnv = process.env;
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    jest.spyOn(core, "getInput").mockImplementation((name, options) => {
 | 
			
		||||
        return jest.requireActual("@actions/core").getInput(name, options);
 | 
			
		||||
    });
 | 
			
		||||
    testUtils.mockServer.listen({
 | 
			
		||||
        onUnhandledRequest: "warn"
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
beforeEach(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -22,10 +28,15 @@ beforeEach(() => {
 | 
			
		|||
    process.env = pristineEnv;
 | 
			
		||||
    delete process.env[Events.Key];
 | 
			
		||||
    delete process.env[RefKey];
 | 
			
		||||
    delete process.env["GITHUB_REPOSITORY"];
 | 
			
		||||
    delete process.env["GITHUB_TOKEN"];
 | 
			
		||||
    delete process.env["GITHUB_ACTION"];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    process.env = pristineEnv;
 | 
			
		||||
    testUtils.mockServer.close();
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("isGhes returns true if server url is not github.com", () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -203,6 +214,94 @@ test("getInputAsBool throws if required and value missing", () => {
 | 
			
		|||
    ).toThrowError();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("deleteCacheByKey returns 'HttpError: 404' when cache is not found.", async () => {
 | 
			
		||||
    const event = Events.Push;
 | 
			
		||||
 | 
			
		||||
    process.env["GITHUB_REPOSITORY"] = "owner/repo";
 | 
			
		||||
    process.env["GITHUB_TOKEN"] =
 | 
			
		||||
        "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";
 | 
			
		||||
    process.env["GITHUB_ACTION"] = "__owner___run-repo";
 | 
			
		||||
    process.env[Events.Key] = event;
 | 
			
		||||
    process.env[RefKey] = "ref/heads/feature";
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const response = await actionUtils.deleteCacheByKey(
 | 
			
		||||
        testUtils.failureCacheKey,
 | 
			
		||||
        "owner",
 | 
			
		||||
        "repo"
 | 
			
		||||
    );
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith(
 | 
			
		||||
        expect.stringMatching(/404: Not Found/i)
 | 
			
		||||
    );
 | 
			
		||||
    expect(response).toBeInstanceOf(RequestError);
 | 
			
		||||
    expect(response).toMatchObject({
 | 
			
		||||
        name: "HttpError",
 | 
			
		||||
        status: 404
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("deleteCacheByKey returns 'HttpError: 401' on an invalid non-mocked request.", async () => {
 | 
			
		||||
    const event = Events.Push;
 | 
			
		||||
 | 
			
		||||
    process.env["GITHUB_REPOSITORY"] = "owner/repo";
 | 
			
		||||
    process.env["GITHUB_TOKEN"] =
 | 
			
		||||
        "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";
 | 
			
		||||
    process.env["GITHUB_ACTION"] = "__owner___run-repo";
 | 
			
		||||
    process.env[Events.Key] = event;
 | 
			
		||||
    process.env[RefKey] = "ref/heads/feature";
 | 
			
		||||
    await nock.enableNetConnect();
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const response = await actionUtils.deleteCacheByKey(
 | 
			
		||||
        testUtils.passThroughCacheKey,
 | 
			
		||||
        "owner",
 | 
			
		||||
        "repo"
 | 
			
		||||
    );
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith(
 | 
			
		||||
        expect.stringMatching(/401: Bad Credentials/i)
 | 
			
		||||
    );
 | 
			
		||||
    expect(response).toBeInstanceOf(RequestError);
 | 
			
		||||
    expect(response).toMatchObject({
 | 
			
		||||
        name: "HttpError",
 | 
			
		||||
        status: 401
 | 
			
		||||
    });
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("deleteCacheByKey returns matched cache data when successful.", async () => {
 | 
			
		||||
    const event = Events.Push;
 | 
			
		||||
 | 
			
		||||
    process.env["GITHUB_REPOSITORY"] = "owner/repo";
 | 
			
		||||
    process.env["GITHUB_TOKEN"] =
 | 
			
		||||
        "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";
 | 
			
		||||
    process.env["GITHUB_ACTION"] = "__owner___run-repo";
 | 
			
		||||
    process.env[Events.Key] = event;
 | 
			
		||||
    process.env[RefKey] = "ref/heads/feature";
 | 
			
		||||
 | 
			
		||||
    const expectedResponse = {
 | 
			
		||||
        id: expect.any(Number),
 | 
			
		||||
        ref: expect.any(String),
 | 
			
		||||
        key: expect.any(String),
 | 
			
		||||
        version: expect.any(String),
 | 
			
		||||
        last_accessed_at: expect.any(String),
 | 
			
		||||
        created_at: expect.any(String),
 | 
			
		||||
        size_in_bytes: expect.any(Number)
 | 
			
		||||
    };
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const response = await actionUtils.deleteCacheByKey(
 | 
			
		||||
        testUtils.successCacheKey,
 | 
			
		||||
        "owner",
 | 
			
		||||
        "repo"
 | 
			
		||||
    );
 | 
			
		||||
    expect(response).toMatchObject({
 | 
			
		||||
        data: expect.objectContaining({
 | 
			
		||||
            total_count: expect.any(Number),
 | 
			
		||||
            actions_caches: expect.arrayContaining([
 | 
			
		||||
                expect.objectContaining(expectedResponse)
 | 
			
		||||
            ])
 | 
			
		||||
        })
 | 
			
		||||
    });
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("isCacheFeatureAvailable for ac enabled", () => {
 | 
			
		||||
    jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => true);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, RefKey } from "../src/constants";
 | 
			
		||||
import { restoreRun } from "../src/restoreImpl";
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +10,7 @@ import * as testUtils from "../src/utils/testUtils";
 | 
			
		|||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
 | 
			
		||||
        (key, cacheResult) => {
 | 
			
		||||
            const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +55,10 @@ afterEach(() => {
 | 
			
		|||
    delete process.env[RefKey];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with no cache found", async () => {
 | 
			
		||||
    const path = "node_modules";
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, RefKey } from "../src/constants";
 | 
			
		||||
import { restoreImpl } from "../src/restoreImpl";
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +11,7 @@ import * as testUtils from "../src/utils/testUtils";
 | 
			
		|||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
 | 
			
		||||
        (key, cacheResult) => {
 | 
			
		||||
            const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +56,10 @@ afterEach(() => {
 | 
			
		|||
    delete process.env[RefKey];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with invalid event outputs warning", async () => {
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, RefKey } from "../src/constants";
 | 
			
		||||
import { restoreOnlyRun } from "../src/restoreImpl";
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +10,7 @@ import * as testUtils from "../src/utils/testUtils";
 | 
			
		|||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
 | 
			
		||||
        (key, cacheResult) => {
 | 
			
		||||
            const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +56,10 @@ afterEach(() => {
 | 
			
		|||
    delete process.env[RefKey];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("restore with no cache found", async () => {
 | 
			
		||||
    const path = "node_modules";
 | 
			
		||||
    const key = "node-test";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, RefKey } from "../src/constants";
 | 
			
		||||
import { saveRun } from "../src/saveImpl";
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +12,7 @@ jest.mock("@actions/cache");
 | 
			
		|||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    jest.spyOn(core, "getInput").mockImplementation((name, options) => {
 | 
			
		||||
        return jest.requireActual("@actions/core").getInput(name, options);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -73,10 +75,14 @@ afterEach(() => {
 | 
			
		|||
    delete process.env[RefKey];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with valid inputs uploads a cache", async () => {
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, RefKey } from "../src/constants";
 | 
			
		||||
import { saveImpl } from "../src/saveImpl";
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +13,19 @@ jest.mock("@actions/cache");
 | 
			
		|||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    testUtils.mockServer.listen({
 | 
			
		||||
        onUnhandledRequest: "warn"
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "deleteCacheByKey").mockImplementation(
 | 
			
		||||
        (key: string, owner: string, repo: string) => {
 | 
			
		||||
            return jest
 | 
			
		||||
                .requireActual("../src/utils/actionUtils")
 | 
			
		||||
                .deleteCacheByKey(key, owner, repo);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getInput").mockImplementation((name, options) => {
 | 
			
		||||
        return jest.requireActual("@actions/core").getInput(name, options);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +66,14 @@ beforeAll(() => {
 | 
			
		|||
        const actualUtils = jest.requireActual("../src/utils/actionUtils");
 | 
			
		||||
        return actualUtils.isValidEvent();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(actionUtils, "logWarning").mockImplementation(
 | 
			
		||||
        (message: string) => {
 | 
			
		||||
            return jest
 | 
			
		||||
                .requireActual("../src/utils/actionUtils")
 | 
			
		||||
                .logWarning(message);
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
beforeEach(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +91,13 @@ afterEach(() => {
 | 
			
		|||
    testUtils.clearInputs();
 | 
			
		||||
    delete process.env[Events.Key];
 | 
			
		||||
    delete process.env[RefKey];
 | 
			
		||||
    delete process.env["GITHUB_TOKEN"];
 | 
			
		||||
    delete process.env["GITHUB_REPOSITORY"];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    testUtils.mockServer.close();
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with invalid event outputs warning", async () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +117,7 @@ test("save with no primary key in state outputs warning", async () => {
 | 
			
		|||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const savedCacheKey = testUtils.successCacheKey;
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
        // Cache Entry State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +166,7 @@ test("save on GHES with AC available", async () => {
 | 
			
		|||
    jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -179,8 +208,10 @@ test("save on GHES with AC available", async () => {
 | 
			
		|||
test("save with exact match returns early", async () => {
 | 
			
		||||
    const infoMock = jest.spyOn(core, "info");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
    testUtils.setInput(Inputs.RefreshCache, "false");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const savedCacheKey = primaryKey;
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -207,7 +238,7 @@ test("save with missing input outputs warning", async () => {
 | 
			
		|||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -235,7 +266,7 @@ test("save with large cache outputs warning", async () => {
 | 
			
		|||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +311,7 @@ test("save with reserve cache failure outputs warning", async () => {
 | 
			
		|||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +358,7 @@ test("save with server error outputs warning", async () => {
 | 
			
		|||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -368,7 +399,7 @@ test("save with server error outputs warning", async () => {
 | 
			
		|||
test("save with valid inputs uploads a cache", async () => {
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = "Linux-node-";
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
| 
						 | 
				
			
			@ -406,3 +437,98 @@ test("save with valid inputs uploads a cache", async () => {
 | 
			
		|||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with cache hit and refresh-cache will try to delete and re-create entry", async () => {
 | 
			
		||||
    process.env["GITHUB_REPOSITORY"] = "owner/repo";
 | 
			
		||||
    process.env["GITHUB_TOKEN"] =
 | 
			
		||||
        "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";
 | 
			
		||||
    process.env["GITHUB_ACTION"] = "__owner___run-repo";
 | 
			
		||||
 | 
			
		||||
    const infoMock = jest.spyOn(core, "info");
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = primaryKey;
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
        // Cache Entry State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return savedCacheKey;
 | 
			
		||||
        })
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return primaryKey;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    const inputPath = "node_modules";
 | 
			
		||||
    testUtils.setInput(Inputs.RefreshCache, "true");
 | 
			
		||||
    testUtils.setInput(Inputs.Path, inputPath);
 | 
			
		||||
    testUtils.setInput(Inputs.UploadChunkSize, "4000000");
 | 
			
		||||
 | 
			
		||||
    const cacheId = 4;
 | 
			
		||||
    const saveCacheMock = jest
 | 
			
		||||
        .spyOn(cache, "saveCache")
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return Promise.resolve(cacheId);
 | 
			
		||||
        });
 | 
			
		||||
    await run(new StateProvider());
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(1);
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledWith(
 | 
			
		||||
        [inputPath],
 | 
			
		||||
        primaryKey,
 | 
			
		||||
        {
 | 
			
		||||
            uploadChunkSize: 4000000
 | 
			
		||||
        },
 | 
			
		||||
        false
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(infoMock).toHaveBeenCalledTimes(3);
 | 
			
		||||
 | 
			
		||||
    expect(infoMock).toHaveBeenNthCalledWith(
 | 
			
		||||
        1,
 | 
			
		||||
        `Cache hit occurred on the primary key ${primaryKey}, attempting to refresh the contents of the cache.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(infoMock).toHaveBeenNthCalledWith(
 | 
			
		||||
        2,
 | 
			
		||||
        `Succesfully deleted cache with key: ${primaryKey}`
 | 
			
		||||
    );
 | 
			
		||||
    expect(infoMock).toHaveBeenNthCalledWith(
 | 
			
		||||
        3,
 | 
			
		||||
        `Cache saved with key: ${primaryKey}`
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with cache hit and refresh-cache will throw a warning if there's no GITHUB_TOKEN", async () => {
 | 
			
		||||
    const logWarningMock = jest.spyOn(actionUtils, "logWarning");
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
    const primaryKey = testUtils.successCacheKey;
 | 
			
		||||
    const savedCacheKey = primaryKey;
 | 
			
		||||
 | 
			
		||||
    const inputPath = "node_modules";
 | 
			
		||||
    testUtils.setInput(Inputs.Path, inputPath);
 | 
			
		||||
    testUtils.setInput(Inputs.RefreshCache, "true");
 | 
			
		||||
 | 
			
		||||
    jest.spyOn(core, "getState")
 | 
			
		||||
        // Cache Entry State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return savedCacheKey;
 | 
			
		||||
        })
 | 
			
		||||
        // Cache Key State
 | 
			
		||||
        .mockImplementationOnce(() => {
 | 
			
		||||
            return primaryKey;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    const saveCacheMock = jest.spyOn(cache, "saveCache");
 | 
			
		||||
    await run(new StateProvider());
 | 
			
		||||
 | 
			
		||||
    expect(saveCacheMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
    expect(logWarningMock).toHaveBeenCalledWith(
 | 
			
		||||
        `Can't refresh cache, either the repository info or a valid token are missing.`
 | 
			
		||||
    );
 | 
			
		||||
    expect(failedMock).toHaveBeenCalledTimes(0);
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import * as cache from "@actions/cache";
 | 
			
		||||
import * as core from "@actions/core";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
import { Events, Inputs, RefKey } from "../src/constants";
 | 
			
		||||
import { saveOnlyRun } from "../src/saveImpl";
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +12,7 @@ jest.mock("@actions/cache");
 | 
			
		|||
jest.mock("../src/utils/actionUtils");
 | 
			
		||||
 | 
			
		||||
beforeAll(() => {
 | 
			
		||||
    nock.disableNetConnect();
 | 
			
		||||
    jest.spyOn(core, "getInput").mockImplementation((name, options) => {
 | 
			
		||||
        return jest.requireActual("@actions/core").getInput(name, options);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +75,10 @@ afterEach(() => {
 | 
			
		|||
    delete process.env[RefKey];
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(() => {
 | 
			
		||||
    nock.enableNetConnect();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test("save with valid inputs uploads a cache", async () => {
 | 
			
		||||
    const failedMock = jest.spyOn(core, "setFailed");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										99165
									
								
								dist/restore-only/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										99165
									
								
								dist/restore-only/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										99165
									
								
								dist/restore/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										99165
									
								
								dist/restore/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										99189
									
								
								dist/save-only/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										99189
									
								
								dist/save-only/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										99189
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										99189
									
								
								dist/save/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
require("nock").disableNetConnect();
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    clearMocks: true,
 | 
			
		||||
    moduleFileExtensions: ["js", "ts"],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										820
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										820
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -44,9 +44,13 @@
 | 
			
		|||
    "eslint-plugin-simple-import-sort": "^7.0.0",
 | 
			
		||||
    "jest": "^28.1.3",
 | 
			
		||||
    "jest-circus": "^27.5.1",
 | 
			
		||||
    "msw": "^0.49.3",
 | 
			
		||||
    "nock": "^13.2.9",
 | 
			
		||||
    "prettier": "^2.8.0",
 | 
			
		||||
    "ts-jest": "^28.0.8",
 | 
			
		||||
    "typescript": "^4.9.3"
 | 
			
		||||
  },
 | 
			
		||||
  "overrides": {
 | 
			
		||||
    "@mswjs/interceptors": "^0.17.7"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,12 @@
 | 
			
		|||
import { Inputs } from "../constants";
 | 
			
		||||
import { rest } from "msw";
 | 
			
		||||
import { setupServer } from "msw/node";
 | 
			
		||||
import nock from "nock";
 | 
			
		||||
 | 
			
		||||
export const successCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
export const failureCacheKey = "Windows-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
export const passThroughCacheKey = "macOS-node-bb828da54c148048dd17899ba9fda624811cfb43";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
 | 
			
		||||
function getInputName(name: string): string {
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +24,7 @@ interface CacheInput {
 | 
			
		|||
    enableCrossOsArchive?: boolean;
 | 
			
		||||
    failOnCacheMiss?: boolean;
 | 
			
		||||
    lookupOnly?: boolean;
 | 
			
		||||
    refreshCache?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function setInputs(input: CacheInput): void {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +41,8 @@ export function setInputs(input: CacheInput): void {
 | 
			
		|||
        setInput(Inputs.FailOnCacheMiss, input.failOnCacheMiss.toString());
 | 
			
		||||
    input.lookupOnly !== undefined &&
 | 
			
		||||
        setInput(Inputs.LookupOnly, input.lookupOnly.toString());
 | 
			
		||||
    input.refreshCache !== undefined &&
 | 
			
		||||
        setInput(Inputs.RefreshCache, input.refreshCache.toString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function clearInputs(): void {
 | 
			
		||||
| 
						 | 
				
			
			@ -42,4 +53,34 @@ export function clearInputs(): void {
 | 
			
		|||
    delete process.env[getInputName(Inputs.EnableCrossOsArchive)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.FailOnCacheMiss)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.LookupOnly)];
 | 
			
		||||
    delete process.env[getInputName(Inputs.RefreshCache)];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* istanbul ignore next */
 | 
			
		||||
export const mockServer = setupServer(rest.delete('https://api.github.com/repos/owner/repo/actions/caches', (req, res, ctx) => {
 | 
			
		||||
    if (req.url?.searchParams?.get('key') === failureCacheKey) {
 | 
			
		||||
        return res(ctx.status(404),
 | 
			
		||||
            ctx.json({
 | 
			
		||||
                message: "Not Found",
 | 
			
		||||
                documentation_url: "https://docs.github.com/rest/actions/cache#delete-github-actions-caches-for-a-repository-using-a-cache-key"
 | 
			
		||||
            }));
 | 
			
		||||
    }
 | 
			
		||||
    else if (req.url?.searchParams?.get('key') === successCacheKey) {
 | 
			
		||||
        return res(ctx.status(200),
 | 
			
		||||
            ctx.json({
 | 
			
		||||
                total_count: 1,
 | 
			
		||||
                actions_caches: [{
 | 
			
		||||
                    id: 15,
 | 
			
		||||
                    ref: "refs/heads/main",
 | 
			
		||||
                    key: successCacheKey,
 | 
			
		||||
                    version: "93a0f912fdb70083e929c1bf564bca2050be1c4e0932f7f9e78465ddcfbcc8f6",
 | 
			
		||||
                    last_accessed_at: "2022-12-29T22:06:42.683333300Z",
 | 
			
		||||
                    created_at: "2022-12-29T22:06:42.683333300Z",
 | 
			
		||||
                    size_in_bytes: 6057793
 | 
			
		||||
                }]
 | 
			
		||||
            }));
 | 
			
		||||
    }
 | 
			
		||||
    else if (req.url?.searchParams?.get('key') === passThroughCacheKey) {
 | 
			
		||||
        return req.passthrough();
 | 
			
		||||
    }
 | 
			
		||||
}));
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user