Streamline button configuraton validation logic

This commit is contained in:
Philipp Stracker 2024-10-08 18:47:32 +02:00
parent 560ec32e26
commit f41fa4f951
No known key found for this signature in database
3 changed files with 113 additions and 59 deletions

View file

@ -217,33 +217,31 @@ class ApplePayButton extends PaymentButton {
/** /**
* @inheritDoc * @inheritDoc
*/ */
validateConfiguration( silent = false ) { registerValidationRules( invalidIf, validIf ) {
const validEnvs = [ 'PRODUCTION', 'TEST' ]; invalidIf(
() =>
[ 'TEST', 'PRODUCTION' ].includes(
this.buttonConfig.environment
),
`Invalid environment: ${ this.buttonConfig.environment }`
);
const isInvalid = ( ...args ) => { validIf( () => this.isPreview );
if ( ! silent ) {
this.error( ...args );
}
return false;
};
if ( ! validEnvs.includes( this.buttonConfig.environment ) ) { invalidIf(
return isInvalid( () => ! this.#applePayConfig,
'Invalid environment:', 'No API configuration - missing configure() call?'
this.buttonConfig.environment );
);
}
// Preview buttons only need a valid environment. invalidIf(
if ( this.isPreview ) { () => ! this.#transactionInfo,
return true; 'No transactionInfo - missing configure() call?'
} );
if ( ! typeof this.contextHandler?.validateContext() ) { invalidIf(
return isInvalid( 'Invalid context handler.', this.contextHandler ); () => ! this.contextHandler?.validateContext(),
} `Invalid context handler.`
);
return true;
} }
/** /**

View file

@ -192,6 +192,13 @@ export default class PaymentButton {
*/ */
#button = null; #button = null;
/**
* List of checks to perform to verify the PaymentButton has is configured correctly.
*
* @type {{check, errorMessage, shouldPass}[]}
*/
#validationChecks = [];
/** /**
* Factory method to create a new PaymentButton while limiting a single instance per context. * Factory method to create a new PaymentButton while limiting a single instance per context.
* *
@ -305,6 +312,11 @@ export default class PaymentButton {
); );
this.applyButtonStyles( this.#buttonConfig ); this.applyButtonStyles( this.#buttonConfig );
this.registerValidationRules(
this.#assertIsInvalid.bind( this ),
this.#assertIsValid.bind( this )
);
apmButtonsInit( this.#ppcpConfig ); apmButtonsInit( this.#ppcpConfig );
this.initEventListeners(); this.initEventListeners();
} }
@ -634,16 +646,74 @@ export default class PaymentButton {
this.#logger.group( label ); this.#logger.group( label );
} }
/**
* Register a validation check that marks the configuration as invalid when passed.
*
* @param {Function} check - A function that returns a truthy value if the check passes.
* @param {string} errorMessage - The error message to display if the check fails.
*/
#assertIsInvalid( check, errorMessage ) {
this.#validationChecks.push( {
check,
errorMessage,
shouldPass: false,
} );
}
/**
* Register a validation check that instantly marks the configuration as valid when passed.
*
* @param {Function} check - A function that returns a truthy value if the check passes.
*/
#assertIsValid( check ) {
this.#validationChecks.push( { check, shouldPass: true } );
}
/**
* Defines a series of validation steps to ensure the payment button is configured correctly.
*
* Each validation step is executed in the order they are defined within this method.
*
* If a validation step using `invalidIf` returns true, the configuration is immediately considered
* invalid, and an error message is logged. Conversely, if a validation step using `validIf`
* returns true, the configuration is immediately considered valid.
*
* If no validation step returns true, the configuration is assumed to be valid by default.
*
* @param {(condition: () => boolean, errorMessage: string) => void} invalidIf - Registers a validation step that fails if the condition returns true.
* @param {(condition: () => boolean) => void} validIf - Registers a validation step that passes if the condition returns true.
*/
registerValidationRules( invalidIf, validIf ) {}
/** /**
* Determines if the current button instance has valid and complete configuration details. * Determines if the current button instance has valid and complete configuration details.
* Used during initialization to decide if the button can be initialized or should be skipped. * Used during initialization to decide if the button can be initialized or should be skipped.
* *
* Can be implemented by the derived class. * All required validation steps must be registered in the constructor of the derived class
* using `this.addValidationFailure()` or `this.addValidationSuccess()`.
* *
* @param {boolean} [silent=false] - Set to true to suppress console errors. * @param {boolean} [silent=false] - Set to true to suppress console errors.
* @return {boolean} True indicates the config is valid and initialization can continue. * @return {boolean} True indicates the config is valid and initialization can continue.
*/ */
validateConfiguration( silent = false ) { validateConfiguration( silent = false ) {
for ( const step of this.#validationChecks ) {
const result = step.check();
if ( step.shouldPass && result ) {
// If a success check passes, mark as valid immediately.
return true;
}
if ( ! step.shouldPass && result ) {
// If a failure check passes, mark as invalid.
if ( ! silent && step.errorMessage ) {
this.error( step.errorMessage );
}
return false;
}
}
return true; return true;
} }

View file

@ -215,45 +215,31 @@ class GooglepayButton extends PaymentButton {
/** /**
* @inheritDoc * @inheritDoc
*/ */
validateConfiguration( silent = false ) { registerValidationRules( invalidIf, validIf ) {
const validEnvs = [ 'PRODUCTION', 'TEST' ]; invalidIf(
() =>
[ 'TEST', 'PRODUCTION' ].includes(
this.buttonConfig.environment
),
`Invalid environment: ${ this.buttonConfig.environment }`
);
const isInvalid = ( ...args ) => { validIf( () => this.isPreview );
if ( ! silent ) {
this.error( ...args );
}
return false;
};
if ( ! validEnvs.includes( this.buttonConfig.environment ) ) { invalidIf(
return isInvalid( () => ! this.googlePayConfig,
'Invalid environment:', 'No API configuration - missing configure() call?'
this.buttonConfig.environment );
);
}
// Preview buttons only need a valid environment. invalidIf(
if ( this.isPreview ) { () => ! this.transactionInfo,
return true; 'No transactionInfo - missing configure() call?'
} );
if ( ! this.googlePayConfig ) { invalidIf(
return isInvalid( () => ! this.contextHandler?.validateContext(),
'No API configuration - missing configure() call?' `Invalid context handler.`
); );
}
if ( ! this.transactionInfo ) {
return isInvalid(
'No transactionInfo - missing configure() call?'
);
}
if ( ! typeof this.contextHandler?.validateContext() ) {
return isInvalid( 'Invalid context handler.', this.contextHandler );
}
return true;
} }
/** /**