How are these two components different? - coldfusion

Is one of these better than the other? What's the difference? They seem to be interchangeable
component
{
property name="some_thing" type="string" value="";
}
vs
component
{
this.some_thing = "";
}

cfproperty
Post CF8, 'cfproperty' allows one to set an implicit setter/getter.
It is also used in the creation of web services & ORM applications and has a vast array of configuration properties:
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-p-q/cfproperty.html
Setter/getter
com/foo.cfc
component accessors='true' {
// set properties & variables above any component methods
property name='bar' type='string';
this.setBar('foo');
function init(){
return this;
}
}
Within a template 'foo.cfm':
foo = new com.foo();
WriteDump(var=foo.getBar());
// foo
'this' scope
The 'this' scope can be accessed both internally & externally to the component.
com/foo.cfc
component {
// set properties & variables above any component methods
this.bar = 'foo';
function init(){
return this;
}
}
Within a template 'foo.cfm':
foo = new com.foo();
WriteDump(var=foo.bar);
// foo
'variables' scope within a component
The variables scope within a component cannot be accessed from outside the component.

Related

how can i store the value returned by my init to be used in my functions

I have the init code and it returns me a structure
public any function init() {
httpService = new http();
httpService.setUrl("#Application.baseURL#security/oauth2/token");
httpService.setMethod("POST");
httpService.addParam(type="header", name="Content-Type", value="application/x-www-form-urlencoded");
httpService.addParam(type="body", value="client_id=#application.clientID#&client_secret=#application.clientsecretID#&grant_type=#application.grant_type#");
result = httpService.send().getPrefix();
return this;
}
problem how can i use the token returned by the method in other methods, if i dump the init, i am just getting the functions, how can i use the data returned by the http
just not getting in my head, because the token is alive for 3600
Thanks
As James says, you should store the result of the http call as an instance variable. Here's one way of doing it using a property and specifying accessors=true for the component so that you can call setHttpResult() and getHttpResult() without having to write those methods. using the variables scope which will make it available to other methods within the component, but not outside.
/* Test.cfc */
component name="test"{
property name="httpResult" type="struct";
public any function init(){
//use "var" to ensure the variable is local to the function only
var httpService = new http();
httpService.setUrl("#Application.baseURL#security/oauth2/token");
httpService.setMethod("POST");
httpService.addParam(type="header", name="Content-Type", value="application/x-www-form-urlencoded");
httpService.addParam(type="body", value="client_id=#application.clientID#&client_secret=#application.clientsecretID#&grant_type=#application.grant_type#");
//store the result privately in the instance
variables.httpResult = httpService.send().getPrefix();
return this;
}
public void function someOtherMethod(){
// this method can access the result struct
var returnedContent = variables.httpResult.fileContent;
}
}
You can then use getHttpResult() inside or outside your component. For example from an external script:
test = New test(); // calls the init() method
WriteDump( test.getHttpResult() ); //auto-generated "getter"

Getting values from THIS scope after init function (persistency inside CFC)

I'm initiating a CFC like this.
<cfscript>
lock scope="application" timeout="5" {
application.mycfc = new mycfc();
}
writeOutput(application.mycfc.readVars());
</cfscript>
In the CFC, I'm setting some properties.
component output="false" accessors="true" {
property name="title";
property name="foo";
this.title = "mycfc";
function init() {
this.foo = "bar";
// I can now properly read this.title, or this.foo.
return this;
}
function readVars() {
// Here, I can read this.title, from the constructor space, but I can't
// read this.foo. It's just blank (because the default value of the
// `default` attribute of `property` is "")
}
}
Because of the implementation (caching in Application), I can instead use application.mycfc.foo in readVars().
Because of this name, it's hard to Google for details. I thought it would be persistent throughout the CFC's life, but apparently it is not?
I surely could do something like
var self = application[this.title]; // or application.mycfc
Or perhaps even
this = application[this.title];
In functions where I want to get/set without typing application.mycfc each time.
Just trying to make sure I'm not doing something wrong, or reinventing the wheel.
In my real implementation, I'm pulling from rows from a database to populate a struct.
Scopes in ColdFusion components (.cfc):
this
is the public scope, read/write from anywhere
properties
is a magical scope, read/write only via accessors (a.k.a. getters/setters) from anywhere
variables
is the private scope, read/write only within your component
All of these scopes can coexist, but this.x is NOT the same field as property name="x"!
Since you are using a component with accessors="true", all your property fields can only be read via getter and written via setter. So if you want to write your title property, use setTitle("mycfc"); instead of this.title = "mycfc";. Same goes for the foo property. Use setFoo("bar"); instead of this.foo = "bar";. If you want to read the properties, use application.mycfc.getTitle() and application.mycfc.getFoo(). If you want to set properties at runtime, use application.mycfc.setTitle("something"). Note that writing to a shared scope such as application should happen in a cflock to avoid race conditions (thread-safety).
If you don't need accessors at all, you can simply use public fields instead (accessors is missing here, i.e. set to false):
component output="false" {
this.title = "mycfc";
this.foo = "";
function init() {
this.foo = "bar";
return this;
}
function readVars() {
return this;
}
}
application.mycfc = new mycfc();
writeOutput(application.mycfc.title); // mycfc
writeOutput(application.mycfc.foo); // bar
application.mycfc.title = "something";
writeOutput(application.mycfc.title); // something
writeOutput(application.mycfc.foo); // bar
Public fields are usually not recommended though as they break encapsulation.

How to unit test private methods in Typescript

When I tried to do unit testing for private methods in a Class getting error as private methods are only accessible inside the class. Here I added sample snippet for my class and mocha test. Kindly provide me solution to implement unit test for private methods.
Class Name: Notification.ts
class Notification {
constructor() {}
public validateTempalte() {
return true;
}
private replacePlaceholder() {
return true;
}
}
Unit Test:
import {Notification} from 'Notification';
import * as chai from "chai";
describe("Notification", function(){
describe('#validateTempalte - Validate template', function() {
it('it should return success', function() {
const result = new Notification()
chai.expect(result.validateTempalte()).to.be.equal(true);
});
});
describe('#replacePlaceholder - Replace Placeholder', function() {
it('it should return success', function() {
const result = new Notification()
// As expected getting error "Private is only accessible within class"
chai.expect(result.replacePlaceholder()).to.be.equal(true);
});
});
});
As a workaround, currently, I am changing access specifier of function replacePlaceholder to public. But I don't think its a valid approach.
A possible solution to omit Typescript checks is to access the property dynamically (Not telling wether its good).
myClass['privateProp'] or for methods: myClass['privateMethod']()
Technically, in current versions of TypeScript private methods are only compile-time checked to be private - so you can call them.
class Example {
public publicMethod() {
return 'public';
}
private privateMethod() {
return 'private';
}
}
const example = new Example();
console.log(example.publicMethod()); // 'public'
console.log(example.privateMethod()); // 'private'
I mention this only because you asked how to do it, and that is how you could do it.
Correct Answer
However, that private method must be called by some other method... otherwise it isn't called at all. If you test the behaviour of that other method, you will cover the private method in the context it is used.
If you specifically test private methods, your tests will become tightly coupled to the implementation details (i.e. a good test wouldn't need to be changed if you refactored the implementation).
Disclaimer
If you still test it at the private method level, the compiler might in the future change and make the test fail (i.e. if the compiler made the method "properly" private, or if a future version of ECMAScript added visibility keywords, etc).
In my case, I use the prototype of the object to get access to a private method. It works well and TS does not swear.
For example:
class Example {
private privateMethod() {}
}
describe() {
it('test', () => {
const example = new Example();
const exampleProto = Object.getPrototypeOf(example);
exampleProto.privateMethod();
})
}
If you use a static method then use exampleProto.constructor.privateMethod();.
In HolgerJeromin's comment, the comment issue has a succinct solution that still uses the property syntax.
The solution is to type cast your object / class to any.
Examples:
(<any>myClass).privateMethod();
const value = (<any>myClass).privateValue;
(myClass as any).privateMethod();
const value = (myClass as any).privateValue;
This method satisfies the compiler as well as the VSCode syntax highlighting.
Here are some of my notes from the issue that talks about this
Accessing via a string is more common, although I don't see why it might be more typesafe.
These features are done deliberately, therefore they are helping more than hindering.
There is probably a way to disable this type of feature so people don't copy and paste this code into production. "noImplicitAny": true, might help in the tsconfig.json
Extract out the private function into a separate/stand alone function, but don't export it externally.
This is somewhat semantically correct, since after all — a private function is private and should not be accessed by anyone except the class itself.
My subjective solution: you could define a new testing-only interface that extends the original one by adding the private methods as (implicitly public) interface methods. Then, you cast the instantiated object to this new test type. This satisfies both tsc and VS code type checking. Your example with my solution:
interface INotification {
validateTemplate(): boolean,
}
class Notification implements INotification {
constructor() {}
public validateTemplate() {
return true;
}
private replacePlaceholder() {
return true;
}
}
Testing:
import {Notification} from 'Notification';
import * as chai from "chai";
interface INotificationTest extends INotification {
replacePlaceholder(): boolean;
}
describe("Notification", function(){
describe('#validateTemplate - Validate template', function() {
it('it should return success', function() {
const result = new Notification() as INotificationTest;
chai.expect(result.validateTemplate()).to.be.equal(true);
});
});
describe('#replacePlaceholder - Replace Placeholder', function() {
it('it should return success', function() {
const result = new Notification() as INotificationTest;
// Works!
chai.expect(result.replacePlaceholder()).to.be.equal(true);
});
});
});
Advantages:
tsc and vs code do not complain
IntelliSense (or any other autocomplete) works
simple (subjectively)
If you don't want to define the original interface (INotification), you could just fully define the test one (INotificationTest) instead of extending and cast it in the same manner.
Disadvantages:
Added boilerplate
Need to have both of the interfaces updated and in sync
Potentially introducing bugs by explicitly casting as a non original type.
I leave it up to you to decide whether this is worth it or no. In my case, the positives outweigh the negatives. I have tested this with jest, but I assume that mocha.js is no different here.
Edit: but generally I would agree with Fenton's answer
// module.ts
private async privateMethod = () => "private method executed"
public async testPrivateMethods(...args) {
if (process.env.NODE_ENV === 'development') {
return this.privateMethod(...args);
}
}
Now we can reach our private method to test. In jest file:
// module.spec.js
describe('Module', () => {
let service: Module = new Module();
it('private method should be defined', () => {
expect(service.testPrivateMethods).toBeDefined();
});
}
You need to set your enviroment variable name of NODE_ENV must be development.
// .env
NODE_ENV="development"
The fun thing is that it's just a typescript error (not javascript), so you can fix it with
// #ts-expect-error
and everything works fine.
I consider it as a legitimate solution, as the goal was to suppress typescript in this particular case.
Since private methods are not accessible outside class, you can have another public method which calls replacePlaceholder() in Notification class and then test the public method.

Confused about PhpSpec stubs and mocks again

I'm building a Laravel 5 application at the moment and have gotten myself confused about how to mock things in PhpSpec.
I'm building a schedule times validator that requires the intended schedule to be checked against all current schedules and see if there's any overlap (events are not allowed to overlap).
I need to pull in the schedules in question so I can test against them. At the moment it's a very basic whereBetween query, but it's going to get a lot more complicated as there'll be recurring schedules to check against as well.
So here's my stripped down class. I really just want to test the doesNotOverlap function.
use App\Schedule;
class ScheduleTimesValidator
{
protected $schedule;
public function __construct(Schedule $schedule)
{
$this->schedule = $schedule;
}
public function doesNotOverlap($slug, $intended)
{
$schedules = $this->getSchedulesBetween($slug, $intended);
if(empty($schedules)) return true;
return false;
}
protected function getSchedulesBetween($slug, $intended)
{
// Casting to array to make testing a little easier
return $this->schedule->whereIsRecurring(false)
->ofChurch($slug)
->whereBetween('start', [$intended['start'], $intended['end']])
->get()->toArray();
}
and here's my Spec
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ScheduleTimesValidatorSpec extends ObjectBehavior
{
protected $validIntended = [
'start' => '2015-12-01 12:00:00',
'end' => '2015-12-01 13:00:00'
];
protected $churchNonRecurringSchedules = [
['start' => '2014-11-20 13:00:00', 'end' => '2014-11-21 14:00:00'],
['start' => '2014-11-23 10:36:07', 'end' => '2014-11-23 11:36:07'],
];
function let($schedule)
{
$schedule->beADoubleOf('App\Schedule');
$this->beConstructedWith($schedule);
}
function it_is_initializable()
{
$this->shouldHaveType('App\Validation\ScheduleTimesValidator');
}
function it_should_return_true_if_it_does_not_overlap($schedule)
{
// $schedule->any()->willReturn([]);
// $schedule->whereIsRecurring()->shouldBeCalled();
// $schedule->whereIsRecurring(false)->ofChurch()->whereBetween()->get()->toArray()->willReturn([]);
// $schedule->willReturn([]);
// $this->getSchedulesBetween('slug', $this->validIntended)->willReturn([]);
$this->doesNotOverlap('slug', $this->validIntended)->shouldReturn(true);
}
// Tear Down
function letgo() {}
}
If I run it like that I get:
! it should return true if it does not overlap
method 'Double\App\Schedule\P8::whereIsRecurring()' not found.
I tried (as you can see) various commented out things to mock what $schedule will return, but that doesn't seem to work.
So I guess I want to mock the protected getSchedulesBetween method in the class, but doing things like $this->getSchedulesBetween($arg, $arg)->willReturn(blah) doesn't work.
Do I need to pull getSchedulesBetween() out of the class and move it into another class and then mock that? Or do I need to push $this->schedule->blah into the doestNotOverlap method so I can mock what $schedule will return?
I don't want to actually test the App\Schedule Laravel Model - I just want to mock what it's returning and will be hardcoding a variety of queries that will be run to get the different model results.
End of a long day here so brain a little zonked.
Update 2014-10-23
So I created a scope on my Schedule model
public function scopeSchedulesBetween($query, $slug, $intended)
{
return $query->whereIsRecurring(false)
->ofChurch($slug)
->whereBetween('start', [$intended['start'], $intended['end']]);
}
Then created a new App\Helpers\ScheduleQueryHelper which instantiated App\Schedule as a variable and added this method:
public function getSchedulesBetween($slug, $intended)
{
return $this->schedule->schedulesBetween($slug, $intended)->get()->toArray();
}
Then updated my spec to do
function let($scheduleQueryHelper)
{
$scheduleQueryHelper->beADoubleOf('App\Helpers\ScheduleQueryHelper');
$this->beConstructedWith($scheduleQueryHelper);
}
function it_should_return_true_if_it_does_not_overlap($scheduleQueryHelper)
{
$scheduleQueryHelper->getSchedulesBetween('slug', $this->validIntended)->willReturn([]);
$this->doesNotOverlap('slug', $this->validIntended)->shouldReturn(true);
}
And back in my ScheduleTimesValidator class did
public function doesNotOverlap($slug, $intended)
{
$schedules = $this->scheduleQueryHelper->getSchedulesBetween($slug, $intended);
if(empty($schedules)) {
return true;
}
return false;
}
And now PhpSpec is mocking that other class ok. However this seems like a very roundabout way to be doing things.

Spark List in Actionscript: Passing Layout & itemRenderer in construtctor

I am trying to create a generic List, where I can pass the layout & item renderer as parameters.
Since it is not possible to pass parameters to a MXML component's Constructor, I figured I should create my List in Actionscript.
I figured it would go something like this:
public class GenericList extends List {
public function GenericList(iR:ItemRenderer, ac:ArrayCollection, layout:LayoutBase) {
super();
this.dataProvider = ac;
this.layout = ... // don't even have access to this.layout
this.itemRenderer = iR // Cannot pass itemRender
}
I would prefer to have the List in MXML (because It will be easier using states later), but If I am forced to use pure Actionscript so I can instantiate it and pass in parameters, any help would go a long way.
You cannot set the itemRenderer property of a list must implement IClassFactory. So your assignment would look like this:
public function GenericList(cf:ClassFactory, ac:ArrayCollection, layout:LayoutBase) {
And the instantiation would be:
var myList:GenericList = new GenericList( new ClassFactory( com.company.renderers.MyItemRenderer, ....);
Regarding the layout:
List essentially wraps DataGroup, so it is the datagroup's layout that you need to access. However, dataGroup will not necessarily be instantiated yet. So you might have to create a private property that you then utilize in commitProperties.
private var _myLayout:LayoutBase; (populate in constructor via getter/setter)
protected var layoutInvalidated:Boolean;
public function set myLayout( layout:LayoutBase):void {
_myLayout = layout;
layoutInvalidated = true;
}
override protected function commitProperties():void {
super.commitProperties();
if( layoutInvalidated && dataGroup && dataGroup.layout ) {
layoutInvalidated = false;
dataGroup.layout = _myLayout;
}
}