Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

Commit

Permalink
Merge branch '5.x.x' into dependabot/github_actions/dot-github/workfl…
Browse files Browse the repository at this point in the history
…ows/5.x.x/actions/setup-node-3
  • Loading branch information
JAdshead authored Sep 6, 2023
2 parents 228e60f + 09eac6b commit b2d108f
Show file tree
Hide file tree
Showing 17 changed files with 1,824 additions and 19,851 deletions.
108 changes: 80 additions & 28 deletions __tests__/server/config/env/runTime.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,57 @@ jest.mock('@americanexpress/env-config-utils', () => {
return actualRuntimeConfigUtils;
});

expect.extend({
toValidateURL(input) {
let passNegativeCase;
let passPositiveCase;
try {
input('//example.com/path');
input('/path');
passNegativeCase = false;
} catch (e) {
passNegativeCase = true;
}
try {
input('https://example.com/path');
passPositiveCase = true;
} catch (e) {
passPositiveCase = false;
}
return {
pass: passNegativeCase && passPositiveCase,
message: () => `${this.utils.matcherHint('toValidateURL', undefined, '')
}\n\nExpected function to validate input is a fetchable URL in Node`,
};
},
toValidatePositiveInteger(input) {
let passNegativeCase;
let passPositiveCase;
try {
input('string that evaluates to NaN');
input('0');
input('-6');
input('4.3');
passNegativeCase = false;
} catch (e) {
passNegativeCase = true;
}
try {
input('1');
input('3001');
input(undefined);
passPositiveCase = true;
} catch (e) {
passPositiveCase = false;
}
return {
pass: passNegativeCase && passPositiveCase,
message: () => `${this.utils.matcherHint('toValidatePositiveInteger', undefined, '')
}\n\nExpected function to validate input is a positive integer`,
};
},
});

describe('runTime', () => {
// eslint-disable-next-line no-console
const origConsoleInfo = console.info;
Expand Down Expand Up @@ -86,25 +137,6 @@ describe('runTime', () => {
jest.resetAllMocks();
});

function nodeUrl(entry) {
return () => {
expect(() => entry.validate('https://example.com/path')).not.toThrow();
expect(() => entry.validate('/path')).toThrow();
};
}

function positiveInteger(entry) {
return () => {
expect(() => entry.validate('1')).not.toThrow();
expect(() => entry.validate('3001')).not.toThrow();
expect(() => entry.validate(undefined)).not.toThrow();
expect(() => entry.validate('string that evaluates to NaN')).toThrow();
expect(() => entry.validate('0')).toThrow();
expect(() => entry.validate('-6')).toThrow();
expect(() => entry.validate('4.3')).toThrow();
};
}

it('has a name on every entry', () => {
const runTime = require('../../../../src/server/config/env/runTime').default;
runTime.forEach((entry) => {
Expand Down Expand Up @@ -281,8 +313,9 @@ describe('runTime', () => {
expect(holocronModuleMapPath.defaultValue()).not.toBeDefined();
});

// eslint-disable-next-line jest/expect-expect -- assertion is in nodeUrl
it('ensures node can reach the URL', nodeUrl(holocronModuleMapPath));
it('ensures node can reach the URL', () => {
expect(holocronModuleMapPath.validate).toValidateURL();
});

it('should use port numbers specified via HTTP_ONE_APP_DEV_CDN_PORT', () => {
process.env.NODE_ENV = 'development';
Expand All @@ -300,8 +333,9 @@ describe('runTime', () => {
expect(holocronServerMaxModulesRetry.defaultValue).toBe(undefined);
});

// eslint-disable-next-line jest/expect-expect -- assertion is in positiveInteger
it('validates the value as a positive integer', positiveInteger(holocronServerMaxModulesRetry));
it('validates the value as a positive integer', () => {
expect(holocronServerMaxModulesRetry.validate).toValidatePositiveInteger();
});
});

describe('HOLOCRON_SERVER_MAX_SIM_MODULES_FETCH', () => {
Expand All @@ -313,11 +347,9 @@ describe('runTime', () => {
expect(holocronServerMaxSimModulesFetch.defaultValue).toBe(undefined);
});

// eslint-disable-next-line jest/expect-expect -- assertion is in positiveInteger
it(
'validates the value as a positive integer',
positiveInteger(holocronServerMaxSimModulesFetch)
);
it('validates the value as a positive integer', () => {
expect(holocronServerMaxSimModulesFetch.validate).toValidatePositiveInteger();
});
});

describe('ONE_CLIENT_REPORTING_URL', () => {
Expand Down Expand Up @@ -514,4 +546,24 @@ describe('runTime', () => {
expect(oneEnableServerTracing.normalize('EbwEfbWEFBE')).toBe('false');
});
});

describe('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT', () => {
const otelLogCollectorUrl = getEnvVarConfig('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT');

it('ensures node can reach the URL', () => {
expect(otelLogCollectorUrl.validate).toValidateURL();
});

it('is not required', () => {
expect(() => otelLogCollectorUrl.validate()).not.toThrow();
});
});

describe('OTEL_SERVICE_NAME', () => {
const otelServiceName = getEnvVarConfig('OTEL_SERVICE_NAME');

it('should have a default value of "One App"', () => {
expect(otelServiceName.defaultValue).toBe('One App');
});
});
});
64 changes: 42 additions & 22 deletions __tests__/server/shutdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
* permissions and limitations under the License.
*/

const originalSetImmediate = setImmediate;
const flushPromises = () => new Promise(originalSetImmediate);

let shutdownOtelLogger;

describe('shutdown', () => {
jest.spyOn(global, 'setTimeout').mockImplementation(() => {});
jest.spyOn(global, 'setImmediate').mockImplementation(() => {});
Expand All @@ -28,30 +33,49 @@ describe('shutdown', () => {

function load() {
jest.resetModules();
jest.mock('../../src/server/utils/logging/otel/logger');
({ shutdownOtelLogger } = require('../../src/server/utils/logging/otel/logger'));
return require('../../src/server/shutdown');
}

beforeEach(() => {
jest.clearAllMocks();
signalNames.forEach((signalName) => process.removeAllListeners(signalName));
});

it('shutdown calls the close property of servers added', () => {
it('shutdown calls the close property of servers added', async () => {
const close = jest.fn();
const { addServer, shutdown } = load();
addServer({ close });
expect(close).not.toHaveBeenCalled();
shutdown();
await shutdown();
expect(close).toHaveBeenCalledTimes(1);
});

it('shutdown logs to the console', () => {
console.log.mockClear();
it('shutdown logs to the console', async () => {
const { shutdown } = load();
shutdown();
await shutdown();
expect(console.log).toHaveBeenCalled();
expect(console.log.mock.calls).toMatchSnapshot();
});

it('shuts down the OTel logger', async () => {
const { shutdown } = load();
await shutdown();
expect(shutdownOtelLogger).toHaveBeenCalledTimes(1);
expect(console.error).not.toHaveBeenCalled();
});

it('logs when there is an error shutting down the OTel logger', async () => {
const { shutdown } = load();
const error = new Error('logger failed to shut down');
shutdownOtelLogger.mockImplementationOnce(() => Promise.reject(error));
await shutdown();
expect(shutdownOtelLogger).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenCalledWith(error);
});

signalNames.forEach((signalName) => {
describe(`${signalName}`, () => {
it('calls shutdown', async () => {
Expand All @@ -60,40 +84,40 @@ describe('shutdown', () => {
addServer({ close });
expect(close).not.toHaveBeenCalled();
process.emit(signalName);
await flushPromises();
expect(close).toHaveBeenCalledTimes(1);
});

it('calls process.exit async when sent twice', () => {
process.exit.mockClear();
setImmediate.mockClear();
it('calls process.exit async when sent twice', async () => {
load();
process.emit(signalName);
await flushPromises();
expect(process.exit).not.toHaveBeenCalled();
process.emit(signalName);
await flushPromises();
expect(setImmediate).toHaveBeenCalled();
setImmediate.mock.calls[0][0]();
expect(process.exit).toHaveBeenCalledTimes(1);
});

it('writes an error message when calling process.exit', () => {
console.error.mockClear();
it('writes an error message when calling process.exit', async () => {
load();
process.emit(signalName);
await flushPromises();
expect(console.error).not.toHaveBeenCalled();
process.emit(signalName);
await flushPromises();
expect(setImmediate).toHaveBeenCalled();
setImmediate.mock.calls[0][0]();
expect(console.error).toHaveBeenCalled();
expect(console.error.mock.calls).toMatchSnapshot();
});

it('forcibly exits if still running later on', () => {
it('forcibly exits if still running later on', async () => {
// babel-node bug, fixed but not yet published
process.exit.mockClear();
setTimeout.mockClear();
setImmediate.mockClear();
load();
process.emit(signalName);
await flushPromises();
expect(process.exit).not.toHaveBeenCalled();
expect(setTimeout).toHaveBeenCalledTimes(1);
expect(setTimeout.mock.calls[0][1]).toMatchSnapshot();
Expand All @@ -103,29 +127,25 @@ describe('shutdown', () => {
expect(process.exit).toHaveBeenCalledTimes(1);
});

it('writes an error message if still running later on', () => {
it('writes an error message if still running later on', async () => {
// babel-node bug, fixed but not yet published
process.exit.mockClear();
setTimeout.mockClear();
console.error.mockClear();
load();
process.emit(signalName);
await flushPromises();
expect(console.error).not.toHaveBeenCalled();
expect(setTimeout).toHaveBeenCalledTimes(1);
setTimeout.mock.calls[0][0]();
expect(console.error).toHaveBeenCalled();
expect(console.error.mock.calls).toMatchSnapshot();
});

it('uses node unref to prevent the exit timeout from preventing exiting', () => {
process.exit.mockClear();
setTimeout.mockClear();

it('uses node unref to prevent the exit timeout from preventing exiting', async () => {
const unref = jest.fn();
setTimeout.mockImplementationOnce(() => ({ unref }));

load();
process.emit(signalName);
await flushPromises();
expect(process.exit).not.toHaveBeenCalled();
expect(setTimeout).toHaveBeenCalledTimes(1);
expect(unref).toHaveBeenCalledTimes(1);
Expand Down
Loading

0 comments on commit b2d108f

Please sign in to comment.