From d60d2bef100d89065bfe43a25f6250d3b4365317 Mon Sep 17 00:00:00 2001
From: Dave Hadka <dhadka@github.com>
Date: Tue, 2 Jun 2020 10:21:03 -0500
Subject: [PATCH] Improve string split

---
 __tests__/actionUtils.test.ts | 37 +++++++++++++++++++++++++++++++++++
 __tests__/restore.test.ts     |  7 +++++++
 __tests__/save.test.ts        |  8 ++++++++
 dist/restore/index.js         | 22 ++++++++++++---------
 dist/save/index.js            | 17 +++++++++++-----
 src/restore.ts                | 13 ++++--------
 src/save.ts                   |  7 +++----
 src/utils/actionUtils.ts      | 11 +++++++++++
 8 files changed, 95 insertions(+), 27 deletions(-)

diff --git a/__tests__/actionUtils.test.ts b/__tests__/actionUtils.test.ts
index b75523b..a6dc291 100644
--- a/__tests__/actionUtils.test.ts
+++ b/__tests__/actionUtils.test.ts
@@ -2,9 +2,16 @@ import * as core from "@actions/core";
 
 import { Events, Outputs, RefKey, State } from "../src/constants";
 import * as actionUtils from "../src/utils/actionUtils";
+import * as testUtils from "../src/utils/testUtils";
 
 jest.mock("@actions/core");
 
+beforeAll(() => {
+    jest.spyOn(core, "getInput").mockImplementation((name, options) => {
+        return jest.requireActual("@actions/core").getInput(name, options);
+    });
+});
+
 afterEach(() => {
     delete process.env[Events.Key];
     delete process.env[RefKey];
@@ -157,3 +164,33 @@ test("isValidEvent returns true for event that has a ref", () => {
 
     expect(isValidEvent).toBe(true);
 });
+
+test("getInputAsArray returns empty array if not required and missing", () => {
+    expect(actionUtils.getInputAsArray("foo")).toEqual([]);
+});
+
+test("getInputAsArray throws error if required and missing", () => {
+    expect(() =>
+        actionUtils.getInputAsArray("foo", { required: true })
+    ).toThrowError();
+});
+
+test("getInputAsArray handles single line correctly", () => {
+    testUtils.setInput("foo", "bar");
+    expect(actionUtils.getInputAsArray("foo")).toEqual(["bar"]);
+});
+
+test("getInputAsArray handles multiple lines correctly", () => {
+    testUtils.setInput("foo", "bar\nbaz");
+    expect(actionUtils.getInputAsArray("foo")).toEqual(["bar", "baz"]);
+});
+
+test("getInputAsArray handles different new lines correctly", () => {
+    testUtils.setInput("foo", "bar\r\nbaz");
+    expect(actionUtils.getInputAsArray("foo")).toEqual(["bar", "baz"]);
+});
+
+test("getInputAsArray handles empty lines correctly", () => {
+    testUtils.setInput("foo", "\n\nbar\n\nbaz\n\n");
+    expect(actionUtils.getInputAsArray("foo")).toEqual(["bar", "baz"]);
+});
diff --git a/__tests__/restore.test.ts b/__tests__/restore.test.ts
index 22b6670..8495021 100644
--- a/__tests__/restore.test.ts
+++ b/__tests__/restore.test.ts
@@ -20,6 +20,13 @@ beforeAll(() => {
         const actualUtils = jest.requireActual("../src/utils/actionUtils");
         return actualUtils.isValidEvent();
     });
+
+    jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
+        (name, options) => {
+            const actualUtils = jest.requireActual("../src/utils/actionUtils");
+            return actualUtils.getInputAsArray(name, options);
+        }
+    );
 });
 
 beforeEach(() => {
diff --git a/__tests__/save.test.ts b/__tests__/save.test.ts
index d6653bb..943a2bd 100644
--- a/__tests__/save.test.ts
+++ b/__tests__/save.test.ts
@@ -19,6 +19,14 @@ beforeAll(() => {
         return jest.requireActual("../src/utils/actionUtils").getCacheState();
     });
 
+    jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
+        (name, options) => {
+            return jest
+                .requireActual("../src/utils/actionUtils")
+                .getInputAsArray(name, options);
+        }
+    );
+
     jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
         (key, cacheResult) => {
             return jest
diff --git a/dist/restore/index.js b/dist/restore/index.js
index d5387e1..00349f4 100644
--- a/dist/restore/index.js
+++ b/dist/restore/index.js
@@ -5306,7 +5306,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
     return result;
 };
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = void 0;
+exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = void 0;
 const core = __importStar(__webpack_require__(470));
 const constants_1 = __webpack_require__(694);
 function isExactKeyMatch(key, cacheKey) {
@@ -5350,6 +5350,14 @@ function isValidEvent() {
     return constants_1.RefKey in process.env && Boolean(process.env[constants_1.RefKey]);
 }
 exports.isValidEvent = isValidEvent;
+function getInputAsArray(name, options) {
+    return core
+        .getInput(name, options)
+        .split("\n")
+        .map(s => s.trim())
+        .filter(x => x !== "");
+}
+exports.getInputAsArray = getInputAsArray;
 
 
 /***/ }),
@@ -6835,14 +6843,10 @@ function run() {
             }
             const primaryKey = core.getInput(constants_1.Inputs.Key, { required: true });
             core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
-            const restoreKeys = core
-                .getInput(constants_1.Inputs.RestoreKeys)
-                .split("\n")
-                .filter(x => x !== "");
-            const cachePaths = core
-                .getInput(constants_1.Inputs.Path, { required: true })
-                .split("\n")
-                .filter(x => x !== "");
+            const restoreKeys = utils.getInputAsArray(constants_1.Inputs.RestoreKeys);
+            const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
+                required: true
+            });
             try {
                 const cacheKey = yield cache.restoreCache(cachePaths, primaryKey, restoreKeys);
                 if (!cacheKey) {
diff --git a/dist/save/index.js b/dist/save/index.js
index 2bfc646..f733e9a 100644
--- a/dist/save/index.js
+++ b/dist/save/index.js
@@ -5306,7 +5306,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
     return result;
 };
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = void 0;
+exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = void 0;
 const core = __importStar(__webpack_require__(470));
 const constants_1 = __webpack_require__(694);
 function isExactKeyMatch(key, cacheKey) {
@@ -5350,6 +5350,14 @@ function isValidEvent() {
     return constants_1.RefKey in process.env && Boolean(process.env[constants_1.RefKey]);
 }
 exports.isValidEvent = isValidEvent;
+function getInputAsArray(name, options) {
+    return core
+        .getInput(name, options)
+        .split("\n")
+        .map(s => s.trim())
+        .filter(x => x !== "");
+}
+exports.getInputAsArray = getInputAsArray;
 
 
 /***/ }),
@@ -6600,10 +6608,9 @@ function run() {
                 core.info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
                 return;
             }
-            const cachePaths = core
-                .getInput(constants_1.Inputs.Path, { required: true })
-                .split("\n")
-                .filter(x => x !== "");
+            const cachePaths = utils.getInputAsArray(constants_1.Inputs.Path, {
+                required: true
+            });
             try {
                 yield cache.saveCache(cachePaths, primaryKey);
             }
diff --git a/src/restore.ts b/src/restore.ts
index 568783b..b1f8cca 100644
--- a/src/restore.ts
+++ b/src/restore.ts
@@ -19,15 +19,10 @@ async function run(): Promise<void> {
         const primaryKey = core.getInput(Inputs.Key, { required: true });
         core.saveState(State.CachePrimaryKey, primaryKey);
 
-        const restoreKeys = core
-            .getInput(Inputs.RestoreKeys)
-            .split("\n")
-            .filter(x => x !== "");
-
-        const cachePaths = core
-            .getInput(Inputs.Path, { required: true })
-            .split("\n")
-            .filter(x => x !== "");
+        const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
+        const cachePaths = utils.getInputAsArray(Inputs.Path, {
+            required: true
+        });
 
         try {
             const cacheKey = await cache.restoreCache(
diff --git a/src/save.ts b/src/save.ts
index c7aa5a7..80b656c 100644
--- a/src/save.ts
+++ b/src/save.ts
@@ -31,10 +31,9 @@ async function run(): Promise<void> {
             return;
         }
 
-        const cachePaths = core
-            .getInput(Inputs.Path, { required: true })
-            .split("\n")
-            .filter(x => x !== "");
+        const cachePaths = utils.getInputAsArray(Inputs.Path, {
+            required: true
+        });
 
         try {
             await cache.saveCache(cachePaths, primaryKey);
diff --git a/src/utils/actionUtils.ts b/src/utils/actionUtils.ts
index 9a24061..26bb8c1 100644
--- a/src/utils/actionUtils.ts
+++ b/src/utils/actionUtils.ts
@@ -45,3 +45,14 @@ export function logWarning(message: string): void {
 export function isValidEvent(): boolean {
     return RefKey in process.env && Boolean(process.env[RefKey]);
 }
+
+export function getInputAsArray(
+    name: string,
+    options?: core.InputOptions
+): string[] {
+    return core
+        .getInput(name, options)
+        .split("\n")
+        .map(s => s.trim())
+        .filter(x => x !== "");
+}