Skip to content

Commit

Permalink
Merge pull request #350 from mollie/pimm/better-credential-feedback
Browse files Browse the repository at this point in the history
More helpful error in createMollieClient for missing credentials.
  • Loading branch information
Pimm authored Jul 5, 2024
2 parents 342cedd + 70edc2e commit e767ac4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
26 changes: 26 additions & 0 deletions src/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,30 @@ type Options = Xor<
apiEndpoint?: string;
} & Pick<AxiosRequestConfig, 'adapter' | 'proxy' | 'socketPath' | 'timeout'>;

const falsyDescriptions = new Map<any, string>([
[undefined, 'undefined'],
[null, 'null'],
['', 'an empty string'],
]);

/**
* Returns an error message (string) similar to `"Parameter "×" is null."` if a property with the passed key exists in
* the passed options object, or `null` if said property does not exist.
*/
function describeFalsyOption(options: Options, key: keyof Options) {
if (key in options == false) {
return null;
}
return `Parameter "${key}" is ${falsyDescriptions.get(options[key]) ?? options[key]}.`;
};

/**
* Throws a `TypeError` if the passed options object does not contain an `apiKey` or an `accessToken`.
*/
export function checkCredentials(options: Options) {
if (!options.apiKey && !options.accessToken) {
throw new TypeError(describeFalsyOption(options, 'apiKey') ?? describeFalsyOption(options, 'accessToken') ?? 'Missing parameter "apiKey" or "accessToken".');
}
}

export default Options;
5 changes: 2 additions & 3 deletions src/createMollieClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { version as libraryVersion } from '../package.json';
import caCertificates from './cacert.pem';
import NetworkClient from './communication/NetworkClient';
import TransformingNetworkClient, { Transformers } from './communication/TransformingNetworkClient';
import { checkCredentials } from './Options';
import type Options from './Options';

// Transformers
Expand Down Expand Up @@ -70,9 +71,7 @@ export default function createMollieClient(options: Options) {
);
}

if (!options.apiKey && !options.accessToken) {
throw new TypeError('Missing parameter "apiKey" or "accessToken".');
}
checkCredentials(options);

const networkClient = new NetworkClient({ ...options, libraryVersion, nodeVersion: process.version, caCertificates });

Expand Down
16 changes: 13 additions & 3 deletions tests/unit/createMollieClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import createMollieClient from '../..';

describe('mollie', () => {
it('should fail when no api key is provided', () => {
describe('createMollieClient', () => {
it('should fail when no credentials are provided', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
expect(() => createMollieClient(undefined)).toThrowError(TypeError);
expect(() => createMollieClient({})).toThrow('Missing parameter "apiKey" or "accessToken".');
});

it('should throw a descriptive error when a apiKey is set to null', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
expect(() => createMollieClient({ apiKey: null })).toThrow('Parameter "apiKey" is null.');
});

it('should throw a descriptive error when a apiKey is set to an empty string', () => {
expect(() => createMollieClient({ apiKey: '' })).toThrow('Parameter "apiKey" is an empty string.');
});
});

0 comments on commit e767ac4

Please sign in to comment.