From 19df1001b00025bd2ac1e25f74bd7e26497f6d89 Mon Sep 17 00:00:00 2001
From: Aparna Jyothi <aparnajyothi-y@github.com>
Date: Fri, 31 Jan 2025 13:16:15 +0530
Subject: [PATCH] test cases

---
 __tests__/main.test.ts                        | 126 ++++++++++++++++++
 __tests__/nightly-installer.test.ts           |  96 ++++++++++++-
 __tests__/official-installer.test.ts          |  98 ++++++++++++++
 dist/setup/index.js                           |  10 --
 src/distributions/base-distribution.ts        |   5 -
 .../official_builds/official_builds.ts        |   5 -
 6 files changed, 318 insertions(+), 22 deletions(-)

diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts
index 501741a6..e8d63ef1 100644
--- a/__tests__/main.test.ts
+++ b/__tests__/main.test.ts
@@ -13,6 +13,10 @@ import each from 'jest-each';
 import * as main from '../src/main';
 import * as util from '../src/util';
 import OfficialBuilds from '../src/distributions/official_builds/official_builds';
+import * as installerFactory from '../src/distributions/installer-factory';
+jest.mock('../src/distributions/installer-factory', () => ({
+  getNodejsDistribution: jest.fn()
+}));
 
 describe('main tests', () => {
   let inputs = {} as any;
@@ -281,3 +285,125 @@ describe('main tests', () => {
     });
   });
 });
+
+
+// Mock the necessary modules
+jest.mock('@actions/core');
+jest.mock('./distributions/installer-factory');
+
+// Create a mock object that satisfies the BaseDistribution type
+const createMockNodejsDistribution = () => ({
+  setupNodeJs: jest.fn(),
+  // Mocking other properties required by the BaseDistribution type (adjust based on your actual types)
+  httpClient: {}, // Example for httpClient, replace with proper mock if necessary
+  osPlat: 'darwin', // Example platform ('darwin', 'win32', 'linux', etc.)
+  nodeInfo: {
+    version: '14.x',
+    arch: 'x64',
+    platform: 'darwin',
+  },
+  getDistributionUrl: jest.fn().mockReturnValue('https://nodejs.org/dist/'), // Default distribution URL
+  install: jest.fn(),
+  validate: jest.fn(),
+  // Mock any other methods/properties defined in BaseDistribution
+});
+
+// Define the mock structure for BaseDistribution type (adjust to your actual type)
+interface BaseDistribution {
+  setupNodeJs: jest.Mock;
+  httpClient: object;
+  osPlat: string;
+  nodeInfo: {
+    version: string;
+    arch: string;
+    platform: string;
+  };
+  getDistributionUrl: jest.Mock;
+  install: jest.Mock;
+  validate: jest.Mock;
+}
+
+describe('Mirror URL Tests', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should pass mirror URL correctly when provided', async () => {
+    (core.getInput as jest.Mock).mockImplementation((name: string) => {
+      if (name === 'mirror-url') return 'https://custom-mirror-url.com';
+      if (name === 'node-version') return '14.x';
+      return '';
+    });
+
+    const mockNodejsDistribution = createMockNodejsDistribution();
+    (installerFactory.getNodejsDistribution as unknown as jest.Mock<typeof installerFactory.getNodejsDistribution>).mockReturnValue(mockNodejsDistribution);
+
+    await main.run();
+
+    // Ensure setupNodeJs is called with the correct parameters, including the mirror URL
+    expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith({
+      versionSpec: '14.x',
+      checkLatest: false,
+      auth: undefined,
+      stable: true,
+      arch: 'x64',
+      mirrorURL: 'https://custom-mirror-url.com',
+    });
+  });
+
+  it('should use default mirror URL when no mirror URL is provided', async () => {
+    (core.getInput as jest.Mock).mockImplementation((name: string) => {
+      if (name === 'mirror-url') return '';
+      if (name === 'node-version') return '14.x';
+      return '';
+    });
+
+    const mockNodejsDistribution = createMockNodejsDistribution();
+    (installerFactory.getNodejsDistribution as jest.Mock).mockReturnValue(mockNodejsDistribution);
+
+    await main.run();
+
+    // Expect that setupNodeJs is called with an empty mirror URL (which will default inside the function)
+    expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith(expect.objectContaining({
+      mirrorURL: '', // Default URL is expected to be handled internally
+    }));
+  });
+
+  it('should handle mirror URL with spaces correctly', async () => {
+    (core.getInput as jest.Mock).mockImplementation((name: string) => {
+      if (name === 'mirror-url') return '    https://custom-mirror-url.com   ';
+      if (name === 'node-version') return '14.x';
+      return '';
+    });
+
+    const mockNodejsDistribution = createMockNodejsDistribution();
+    (installerFactory.getNodejsDistribution as jest.Mock).mockReturnValue(mockNodejsDistribution);
+
+    await main.run();
+
+    // Expect that setupNodeJs is called with the trimmed mirror URL
+    expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith(expect.objectContaining({
+      mirrorURL: 'https://custom-mirror-url.com',
+    }));
+  });
+
+  it('should warn if architecture is provided but node-version is missing', async () => {
+    (core.getInput as jest.Mock).mockImplementation((name: string) => {
+      if (name === 'architecture') return 'x64';
+      if (name === 'node-version') return '';
+      return '';
+    });
+
+    const mockWarning = jest.spyOn(core, 'warning');
+    const mockNodejsDistribution = createMockNodejsDistribution();
+    installerFactory.getNodejsDistribution.mockReturnValue(mockNodejsDistribution);
+
+    await main.run();
+
+    expect(mockWarning).toHaveBeenCalledWith(
+      '`architecture` is provided but `node-version` is missing. In this configuration, the version/architecture of Node will not be changed.'
+    );
+    expect(mockNodejsDistribution.setupNodeJs).not.toHaveBeenCalled(); // Setup Node should not be called
+  });
+});
+
diff --git a/__tests__/nightly-installer.test.ts b/__tests__/nightly-installer.test.ts
index 87c43795..1211ea11 100644
--- a/__tests__/nightly-installer.test.ts
+++ b/__tests__/nightly-installer.test.ts
@@ -10,8 +10,8 @@ import osm from 'os';
 import path from 'path';
 import * as main from '../src/main';
 import * as auth from '../src/authutil';
-import {INodeVersion} from '../src/distributions/base-models';
-
+import {INodeVersion, NodeInputs} from '../src/distributions/base-models';
+import NightlyNodejs from '../src/distributions/nightly/nightly_builds';
 import nodeTestManifest from './data/versions-manifest.json';
 import nodeTestDist from './data/node-dist-index.json';
 import nodeTestDistNightly from './data/node-nightly-index.json';
@@ -606,3 +606,95 @@ describe('setup-node', () => {
     );
   });
 });
+// Mock core.info to track the log output
+jest.mock('@actions/core', () => ({
+  info: jest.fn(),
+}));
+
+// Create a subclass to access the protected method for testing purposes
+class TestNightlyNodejs extends NightlyNodejs {
+  public getDistributionUrlPublic() {
+    return this.getDistributionUrl();  // This allows us to call the protected method
+  }
+}
+
+describe('NightlyNodejs', () => {
+
+  it('uses mirror URL when provided', async () => {
+    const mirrorURL = 'https://my.custom.mirror/nodejs/nightly';
+    const nodeInfo: NodeInputs = {
+      mirrorURL: '', versionSpec: '18.0.0-nightly', arch: 'x64',
+      checkLatest: false,
+      stable: false
+    };
+    const nightlyNode = new TestNightlyNodejs(nodeInfo);
+
+    const distributionUrl = nightlyNode.getDistributionUrlPublic();
+    
+    expect(distributionUrl).toBe(mirrorURL);
+    expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`);
+  });
+
+  it('falls back to default distribution URL when no mirror URL is provided', async () => {
+    const nodeInfo: NodeInputs = {
+     versionSpec: '18.0.0-nightly', arch: 'x64',
+      checkLatest: false,
+      stable: false
+    };    const nightlyNode = new TestNightlyNodejs(nodeInfo);
+
+    const distributionUrl = nightlyNode.getDistributionUrlPublic();
+
+    expect(distributionUrl).toBe('https://nodejs.org/download/nightly');
+    expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.');
+  });
+
+  it('logs mirror URL when provided', async () => {
+    const mirrorURL = 'https://custom.mirror/nodejs/nightly';
+    const nodeInfo: NodeInputs = {
+      mirrorURL: '', versionSpec: '18.0.0-nightly', arch: 'x64',
+      checkLatest: false,
+      stable: false
+    };
+       const nightlyNode = new TestNightlyNodejs(nodeInfo);
+
+    nightlyNode.getDistributionUrlPublic();
+    
+    expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`);
+  });
+
+  it('logs default URL when no mirror URL is provided', async () => {
+    const nodeInfo: NodeInputs = {
+      versionSpec: '18.0.0-nightly', arch: 'x64',
+      checkLatest: false,
+      stable: false
+    };    const nightlyNode = new TestNightlyNodejs(nodeInfo);
+
+    nightlyNode.getDistributionUrlPublic();
+
+    expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.');
+  });
+
+  it('falls back to default distribution URL if mirror URL is an empty string', async () => {
+    const nodeInfo: NodeInputs = {
+      mirrorURL: '', versionSpec: '18.0.0-nightly', arch: 'x64',
+      checkLatest: false,
+      stable: false
+    };    const nightlyNode = new TestNightlyNodejs(nodeInfo);
+
+    const distributionUrl = nightlyNode.getDistributionUrlPublic();
+
+    expect(distributionUrl).toBe('https://nodejs.org/download/nightly');
+    expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.');
+  });
+
+  it('falls back to default distribution URL if mirror URL is undefined', async () => {
+    const nodeInfo: NodeInputs = { nodeVersion: '18.0.0-nightly', architecture: 'x64', platform: 'linux' };
+    const nightlyNode = new TestNightlyNodejs(nodeInfo);
+
+    const distributionUrl = nightlyNode.getDistributionUrlPublic();
+
+    expect(distributionUrl).toBe('https://nodejs.org/download/nightly');
+    expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.');
+  });
+
+});
\ No newline at end of file
diff --git a/__tests__/official-installer.test.ts b/__tests__/official-installer.test.ts
index 2d8f17cf..c109f22a 100644
--- a/__tests__/official-installer.test.ts
+++ b/__tests__/official-installer.test.ts
@@ -829,3 +829,101 @@ describe('setup-node', () => {
     );
   });
 });
+describe('OfficialBuilds - Mirror URL functionality', () => {
+  const nodeInfo: NodeInputs = { nodeVersion: '18.0.0-nightly', architecture: 'x64', platform: 'linux', mirrorURL: '' };
+  
+  it('should download using the mirror URL when provided', async () => {
+    const mirrorURL = 'https://my.custom.mirror/nodejs';
+    nodeInfo.mirrorURL = mirrorURL;
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    // Mock download from mirror URL
+    const mockDownloadPath = '/some/temp/path';
+    jest.spyOn(tc, 'downloadTool').mockResolvedValue(mockDownloadPath);
+
+    await officialBuilds.setupNodeJs();
+
+    expect(core.info).toHaveBeenCalledWith('Attempting to download using mirror URL...');
+    expect(core.info).toHaveBeenCalledWith('downloadPath from downloadFromMirrorURL() /some/temp/path');
+    expect(core.addPath).toHaveBeenCalledWith(mockDownloadPath);
+  });
+
+  it('should log a message when mirror URL is used', async () => {
+    const mirrorURL = 'https://my.custom.mirror/nodejs';
+    nodeInfo.mirrorURL = mirrorURL;
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    const mockDownloadPath = '/some/temp/path';
+    jest.spyOn(tc, 'downloadTool').mockResolvedValue(mockDownloadPath);
+
+    await officialBuilds.setupNodeJs();
+
+    expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`);
+  });
+
+  it('should fall back to default URL if mirror URL is not provided', async () => {
+    nodeInfo.mirrorURL = ''; // No mirror URL provided
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    const mockDownloadPath = '/some/temp/path';
+    jest.spyOn(tc, 'downloadTool').mockResolvedValue(mockDownloadPath);
+
+    await officialBuilds.setupNodeJs();
+
+    expect(core.info).toHaveBeenCalledWith('Attempting to download from default Node.js URL...');
+    expect(core.addPath).toHaveBeenCalledWith(mockDownloadPath);
+  });
+
+  it('should log an error and handle failure during mirror URL download', async () => {
+    const mirrorURL = 'https://my.custom.mirror/nodejs';
+    nodeInfo.mirrorURL = mirrorURL;
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    // Simulate an error during the download process
+    const errorMessage = 'Network error';
+    jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error(errorMessage));
+
+    await officialBuilds.setupNodeJs();
+
+    expect(core.info).toHaveBeenCalledWith('Attempting to download using mirror URL...');
+    expect(core.error).toHaveBeenCalledWith(errorMessage);
+    expect(core.debug).toHaveBeenCalledWith(expect.stringContaining('empty stack'));
+  });
+
+  it('should log a fallback message if downloading from the mirror URL fails', async () => {
+    const mirrorURL = 'https://my.custom.mirror/nodejs';
+    nodeInfo.mirrorURL = mirrorURL;
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    // Simulate download failure and fallback to default URL
+    const errorMessage = 'Network error';
+    jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error(errorMessage));
+
+    const mockDownloadPath = '/some/temp/path';
+    jest.spyOn(tc, 'downloadTool').mockResolvedValue(mockDownloadPath);
+
+    await officialBuilds.setupNodeJs();
+
+    expect(core.info).toHaveBeenCalledWith('Failed to download from mirror URL. Falling back to default Node.js URL...');
+    expect(core.addPath).toHaveBeenCalledWith(mockDownloadPath);
+  });
+
+  it('should throw an error if mirror URL is not provided and downloading from both mirror and default fails', async () => {
+    nodeInfo.mirrorURL = ''; // No mirror URL
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    // Simulate failure in both mirror and default download
+    const errorMessage = 'Network error';
+    jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error(errorMessage));
+
+    await expect(officialBuilds.setupNodeJs()).rejects.toThrowError(new Error('Unable to find Node version for platform linux and architecture x64.'));
+  });
+
+  it('should throw an error if mirror URL is undefined and not provided', async () => {
+    nodeInfo.mirrorURL = undefined; // Undefined mirror URL
+    const officialBuilds = new OfficialBuilds(nodeInfo);
+
+    // Simulate a missing mirror URL scenario
+    await expect(officialBuilds.setupNodeJs()).rejects.toThrowError('Mirror URL is undefined');
+  });
+});
\ No newline at end of file
diff --git a/dist/setup/index.js b/dist/setup/index.js
index 1434ce58..4d32a5b6 100644
--- a/dist/setup/index.js
+++ b/dist/setup/index.js
@@ -100157,9 +100157,7 @@ class BaseDistribution {
     getMirrorUrlVersions() {
         return __awaiter(this, void 0, void 0, function* () {
             const initialUrl = this.getDistributionMirrorUrl();
-            core.info('initialUrl from getDistributionMirrorUrl ' + initialUrl);
             const dataUrl = `${initialUrl}/index.json`;
-            core.info('dataUrl from index ' + dataUrl);
             const response = yield this.httpClient.getJson(dataUrl);
             return response.result || [];
         });
@@ -100186,9 +100184,7 @@ class BaseDistribution {
     }
     getNodejsMirrorURLInfo(version) {
         const mirrorURL = this.nodeInfo.mirrorURL;
-        core.info('mirrorURL from getNodejsMirrorURLInfo ' + mirrorURL);
         const osArch = this.translateArchToDistUrl(this.nodeInfo.arch);
-        core.info('osArch from translateArchToDistUrl ' + osArch);
         version = semver_1.default.clean(version) || '';
         const fileName = this.osPlat == 'win32'
             ? `node-v${version}-win-${osArch}`
@@ -100199,7 +100195,6 @@ class BaseDistribution {
                 : `${fileName}.7z`
             : `${fileName}.tar.gz`;
         const url = `${mirrorURL}/v${version}/${urlFileName}`;
-        core.info('url from construct ' + url);
         return {
             downloadUrl: url,
             resolvedVersion: version,
@@ -100729,19 +100724,14 @@ class OfficialBuilds extends base_distribution_1.default {
     downloadFromMirrorURL() {
         return __awaiter(this, void 0, void 0, function* () {
             const nodeJsVersions = yield this.getMirrorUrlVersions();
-            core.info('nodeJsVersions from getMirrorUrVersions ' + nodeJsVersions);
             const versions = this.filterVersions(nodeJsVersions);
-            core.info('versions from filterVersions ' + versions);
             const evaluatedVersion = this.evaluateVersions(versions);
-            core.info('evaluatedVersion from evaluatedVersions ' + evaluatedVersion);
             if (!evaluatedVersion) {
                 throw new Error(`Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.`);
             }
             const toolName = this.getNodejsMirrorURLInfo(evaluatedVersion);
-            core.info('toolName from getNodejsMirrorURLInfo ' + toolName);
             try {
                 const toolPath = yield this.downloadNodejs(toolName);
-                core.info('toolPath from downloadNodejs ' + toolPath);
                 return toolPath;
             }
             catch (error) {
diff --git a/src/distributions/base-distribution.ts b/src/distributions/base-distribution.ts
index 7132d627..185cba3c 100644
--- a/src/distributions/base-distribution.ts
+++ b/src/distributions/base-distribution.ts
@@ -107,10 +107,8 @@ export default abstract class BaseDistribution {
 
   protected async getMirrorUrlVersions(): Promise<INodeVersion[]> {
     const initialUrl = this.getDistributionMirrorUrl();
-    core.info('initialUrl from getDistributionMirrorUrl '+initialUrl);
     
     const dataUrl = `${initialUrl}/index.json`;
-    core.info('dataUrl from index '+dataUrl);
 
     const response = await this.httpClient.getJson<INodeVersion[]>(dataUrl);
     return response.result || [];
@@ -142,10 +140,8 @@ export default abstract class BaseDistribution {
 
   protected getNodejsMirrorURLInfo(version: string) {
     const mirrorURL = this.nodeInfo.mirrorURL;
-    core.info('mirrorURL from getNodejsMirrorURLInfo '+mirrorURL);
     
     const osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch);
-    core.info('osArch from translateArchToDistUrl '+osArch);
     
     version = semver.clean(version) || '';
     const fileName: string =
@@ -160,7 +156,6 @@ export default abstract class BaseDistribution {
         : `${fileName}.tar.gz`;
 
     const url = `${mirrorURL}/v${version}/${urlFileName}`;
-      core.info('url from construct '+url);
 
     return <INodeVersionInfo>{
       downloadUrl: url,
diff --git a/src/distributions/official_builds/official_builds.ts b/src/distributions/official_builds/official_builds.ts
index c6aa23b3..1a26a435 100644
--- a/src/distributions/official_builds/official_builds.ts
+++ b/src/distributions/official_builds/official_builds.ts
@@ -318,14 +318,11 @@ export default class OfficialBuilds extends BaseDistribution {
 
   protected async downloadFromMirrorURL() {
     const nodeJsVersions = await this.getMirrorUrlVersions();
-    core.info('nodeJsVersions from getMirrorUrVersions '+nodeJsVersions);
     const versions = this.filterVersions(nodeJsVersions);
-    core.info('versions from filterVersions '+versions);
 
 
     const evaluatedVersion = this.evaluateVersions(versions);
 
-    core.info('evaluatedVersion from evaluatedVersions '+evaluatedVersion);
 
 
     if (!evaluatedVersion) {
@@ -336,12 +333,10 @@ export default class OfficialBuilds extends BaseDistribution {
 
     const toolName = this.getNodejsMirrorURLInfo(evaluatedVersion);
 
-    core.info('toolName from getNodejsMirrorURLInfo '+toolName);
 
 
     try {
       const toolPath = await this.downloadNodejs(toolName);
-      core.info('toolPath from downloadNodejs '+toolPath);
 
       return toolPath;
     } catch (error) {