Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions models/Component.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ component output="true" accessors="true" {
// Determine if component should be lazy loaded
// If lazy parameter is explicitly provided, use that value
// Otherwise, use the component's lazy preference
local.shouldLazyLoad = isNull( arguments.lazy ) ?
local.shouldLazyLoad = isNull( arguments.lazy ) ?
local.instance._getLazyLoad() : // Use component's preference if no explicit parameter
arguments.lazy; // Use explicit parameter value

Expand Down Expand Up @@ -1115,7 +1115,9 @@ component output="true" accessors="true" {
function _getConstraints(){
if ( variables.keyExists( "constraints" ) ) {
return variables.constraints;
}
}else if ( structKeyExists( this, "constraints" ) ) {
return this.constraints;
}
return [:];
}

Expand Down
8 changes: 6 additions & 2 deletions models/services/ValidationService.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,12 @@ component accessors="true" singleton {
* @return ValidationResult The result of the validation operation.
*/
function validate( wire, target, fields, constraints, locale, excludeFields, includeFields, profiles ){
arguments.target = isNull( arguments.target ) ? arguments.wire._getDataProperties() : arguments.target;
arguments.constraints = isNull( arguments.constraints ) ? arguments.wire._getConstraints() : arguments.constraints;
if( isNull( arguments.target ) ){
// if no target is provided, default to the wire's data properties
arguments.target = arguments.wire._getDataProperties();
// use the wire's constraints if explicit constraints are not provided
arguments.constraints = isNull( arguments.constraints ) ? arguments.wire._getConstraints() : arguments.constraints
}
return getManager().validate( argumentCollection = arguments );
}

Expand Down
21 changes: 21 additions & 0 deletions test-harness/models/validationTest.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
component accessors="true" {

property name="FirstName";
property name="LastName";

this.constraints = {
FirstName : {
required : true,
requiredMessage : "First name is required",
size : "2..50",
sizeMessage : "First name must be 2-50 characters"
},
LastName : {
required : true,
requiredMessage : "Last name is required",
size : "2..50",
sizeMessage : "Last name must be 2-50 characters"
}
};

}
31 changes: 24 additions & 7 deletions test-harness/tests/specs/CBWIRESpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,26 @@ component extends="coldbox.system.testing.BaseTestCase" {
);

expect( renderedHtml ).toInclude( 'Some&##x20;text&##x20;with&##x20;&##x5c;"quotes' );
});
} );

it( "should get constraints when set using this.constraints=", function() {
var testValidationComponent = getInstance("wires.test.validation.validateConstraints1");
var constraints = testValidationComponent._getConstraints();
expect( constraints ).toBeTypeOf( "struct" );
expect( constraints ).toHaveLength( 1 );
expect( constraints ).toHaveKey( "firstname" );
} );

it( "should get constraints when set using constraints=", function() {
var testValidationComponent = getInstance("wires.test.validation.validateConstraints2");
var constraints = testValidationComponent._getConstraints();
expect( constraints ).toBeTypeOf( "struct" );
expect( constraints ).toHaveLength( 1 );
expect( constraints ).toHaveKey( "firstname" );
} );

});

} );

describe("Incoming Requests", function() {

Expand Down Expand Up @@ -727,7 +744,7 @@ component extends="coldbox.system.testing.BaseTestCase" {
var settings = getInstance( "coldbox:modulesettings:cbwire" );
var originalSetting = settings.csrfEnabled;
settings.csrfEnabled = false;

var payload = incomingRequest(
memo = {
"name": "TestComponent",
Expand All @@ -747,12 +764,12 @@ component extends="coldbox.system.testing.BaseTestCase" {
updates = {},
csrfToken = "badToken"
);

// Should not throw an error even with bad token when CSRF is disabled
var response = cbwireController.handleRequest( payload, event );
expect( isStruct( response ) ).toBeTrue();
expect( response.components[1].effects.html ).toInclude( "CBWIRE Slays!" );

// Restore original setting
settings.csrfEnabled = originalSetting;
} );
Expand All @@ -761,10 +778,10 @@ component extends="coldbox.system.testing.BaseTestCase" {
var settings = getInstance( "coldbox:modulesettings:cbwire" );
var originalSetting = settings.csrfEnabled;
settings.csrfEnabled = false;

var token = cbwireController.generateCSRFToken();
expect( token ).toBe( "" );

// Restore original setting
settings.csrfEnabled = originalSetting;
} );
Expand Down
80 changes: 79 additions & 1 deletion test-harness/tests/specs/unit/services/ValidationServiceSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ component extends="coldbox.system.testing.BaseTestCase" {
});

describe( "validate()", function() {
it( "should validate with given target and constraints", function() {

it( "should validate with given target and constraints", function() {
var wire = {};
var target = { "foo": "bar" };
var constraints = { "foo": { "required": true } };
Expand All @@ -61,6 +62,83 @@ component extends="coldbox.system.testing.BaseTestCase" {
var result = validationService.validate( wire );
expect( result ).toHaveKey( "ok" );
});

it( "should validate an object other than the wire itself", function() {
var oValidationTest = getInstance( "validationTest" );
var wire = prepareMock( createStub() );
wire.$( "_getDataProperties", { "bar": "baz" } );
wire.$( "_getConstraints", { "bar": { "required": true } } );
// mock the validate method to return the arguments passed to it so that
// we can validate that the correct mutation of the arguments is occurring
// in the validate() method of the service
mockValidationManager.$(
method = "validate",
callback = function() {
return arguments;
}
);
var result = validationService.validate( wire=wire, target=oValidationTest );
// validate that we do not have the wires constraints and that there
// are no constraints passed to validate() method so that the constraints
// from the object will be used
expect( result ).notToHaveKey( "constraints" );
// validate that we have a target passed into the validate method
expect( result ).toHaveKey( "target" );
// validate that the target contains the constraints from the object
expect( result.target ).toHaveKey( "constraints" );
expect( result.target.constraints ).toBeTypeOf( "struct" );
expect( result.target.constraints ).toHaveLength( 2 );
expect( result.target.constraints ).toHaveKey( "firstname" );
expect( result.target.constraints ).toHaveKey( "lastname" );
expect( result.target.constraints ).notToHaveKey( "bar" );
// get the metadata of the target to validate that it is the correct object and not the wire
var resultTargetMetaData = getMetadata( result.target );
// validate that the target metadata contains the name of the component (validationTest)
expect( resultTargetMetaData ).toHaveKey( "name" );
expect( resultTargetMetaData.name ).toInclude( "validationTest" );
});

it( "shoud validate an object other than the wire itself with custom validation constraints", function() {
var oValidationTest = getInstance( "validationTest" );
var wire = prepareMock( createStub() );
wire.$( "_getDataProperties", { "bar": "baz" } );
wire.$( "_getConstraints", { "bar": { "required": true } } );
var customConstraints = {
password : {
required : true,
requiredMessage : "Password is required",
size : "8..50",
sizeMessage : "Password must be 8-50 characters"
}
};
// mock the validate method to return the arguments passed to it so that
// we can validate that the correct mutation of the arguments is occurring
// in the validate() method of the service
mockValidationManager.$(
method = "validate",
callback = function() {
return arguments;
}
);
var result = validationService.validate( wire=wire, target=oValidationTest, constraints=customConstraints );
// validate that we do not have the wires constraints and that the constraints
// passed to the validate() method are the custom constraints and not the objects
// or wires constraints
expect( result ).toHaveKey( "constraints" );
expect( result.constraints ).toBeTypeOf( "struct" );
expect( result.constraints ).toHaveLength( 1 );
expect( result.constraints ).toHaveKey( "password" );
expect( result.constraints ).notToHaveKey( "lastname" );
expect( result.constraints ).notToHaveKey( "bar" );
// validate that we have a target passed into the validate method
expect( result ).toHaveKey( "target" );
// get the metadata of the target to validate that it is the correct object and not the wire
var resultTargetMetaData = getMetadata( result.target );
// validate that the target metadata contains the name of the component (validationTest)
expect( resultTargetMetaData ).toHaveKey( "name" );
expect( resultTargetMetaData.name ).toInclude( "validationTest" );
});

});

describe( "validateOrFail()", function() {
Expand Down
20 changes: 20 additions & 0 deletions test-harness/wires/test/validation/validateConstraints1.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
component extends="cbwire.models.Component" {

data = {
"firstname": "sdfsad",
"lastname": ""
};
/*
This components DOES use this.constraints=

The cbwire documentation states that you can define constraints using constraints=
https://cbwire.ortusbooks.com/features/form-validation

CBValidation documentation states that you define constraints using this.constraints=
https://coldbox-validation.ortusbooks.com/overview/declaring-constraints/domain-object
*/
this.constraints = {
"firstname": { required: true }
};

}
6 changes: 6 additions & 0 deletions test-harness/wires/test/validation/validateConstraints1.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<cfoutput>
<div>
<input wire:model="firstname" class="form-control" type="text" placeholder="First Name">
<button wire:click="submit">Submit</button>
</div>
</cfoutput>
20 changes: 20 additions & 0 deletions test-harness/wires/test/validation/validateConstraints2.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
component extends="cbwire.models.Component" {

data = {
"firstname": "sdfsad",
"lastname": ""
};
/*
This components DOES use constraints=

The cbwire documentation states that you can define constraints using constraints=
https://cbwire.ortusbooks.com/features/form-validation

CBValidation documentation states that you define constraints using this.constraints=
https://coldbox-validation.ortusbooks.com/overview/declaring-constraints/domain-object
*/
constraints = {
"firstname": { required: true }
};

}
6 changes: 6 additions & 0 deletions test-harness/wires/test/validation/validateConstraints2.cfm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<cfoutput>
<div>
<input wire:model="firstname" class="form-control" type="text" placeholder="First Name">
<button wire:click="submit">Submit</button>
</div>
</cfoutput>
Loading