What is the approach for constructing tests of code that don't have an outcome in the immediate sense?
Let's say we have a very simple (yet quite rude) process:
User signs up to site
Two days pass
Send reminder email
Update some database fields
Ten days pass
Send "c'ya" email
Delete account
I can write tests for each set of sub tasks (email is sent, database is updated, etc). However how do I write well structured tests, that read something like:
"Two days after registration, reminder email should be sent"
"Ten days after registration, account is deleted"
Although I am using PHP and PHPUnit, I feel the question may/may not be language agnostic.
Based on implementation of your event mechanics. Like, when some event listener somewhere in your code receives event user:reminder with user id, then you need just:
1) Test reminder-send script by sending that event manually:
$eventBus->init();
$eventBus->attachListener($reminderListener);
$eventBus->fire(new ReminderEvent($user->id));
$this->expect(...); // reminder must be `sent`
2) Test generation of event when time had passed:
$time = now();
$delay = ...;
$emitter = new RemindEventEmitter($user->id, $time + $delay)
$eventBus->addEmitter($emitter);
$eventBus->setCurrentTime($time); // when we just registered emitter...
$eventBus->run();
$this->expectNot(...); // ... that event _must not_ be fired
$eventBus->setCurrentTime($time + $delay); // manually skip $delay time ...
$eventBus->run();
$this->expect(...); // test that event _must_ be fired
And that event-spawning/dispatching thing ($eventBus in my example) must relay on mockable/replacable time-getter:
// in production code
$eventBus->setCurrentTime(now());
// elsewhere in tests
$eventBus->setCurrentTime(<point in time you want to test against>);
Related
Task:
I am creating a way that a frontend user can send a message and schedule a time for it to be delivered. To accomplish this, I am storing the message info in database tables and then Setting a queue to fire a send function at the appropriate time.
Question:
If the user changes their mind about the time to send the message after this code is executed, is there a way to remove this from the queue and then re add it to fire at a different time?
Example
$data = ['message_id' => $this->messageModel->id];
$queue = Queue::later($this->send_at, 'KurtJensen\Twilio\Classes\SendQueue', $data);
// ==== Everything works great up to this point =======
// Don't know if this will work
// Can I get a queue identifier here?
$this->messageModel->queue_id = $queue->id;
$this->messageModel->save();
Then later to change time:
$this->messageModel= Message::find($id);
$q_id = $this->messageModel->queue_id;
// ==== I doubt this would work or if canceling a queue is possible =======
Queue::cancel($q_id);
$queue = Queue::later($new_time, 'KurtJensen\Twilio\Classes\SendQueue', $data);
$this->messageModel->queue_id = $queue->id;
$this->messageModel->save();
Apologies, since I may not know the terminologies for the salesforce API. I just started programming a connector to interact with salesforce and I am stuck.
I have a requirement, where each time a new entry is added to the Leads section, I will have to retrieve a couple of fields (Firstname and Product Code) and pass it to a different software that makes use of PHP.
<?php
require "conf/config_cleverbridge_connector.inc.php";
require "include/lc_connector.inc.php";
// Start of Main program
// Read basic parameters
if ($LC_Username === "")
{
$LC_Username = readParam("USER");
}
if ($LC_Password === "")
{
$LC_Password = readParam("PASSWORD");
}
$orderID = "";
$customerID = substr(readParam("PURCHASE_ID"), 0, 10);
$comment = readParam("EMAIL")."-".readParam("PURCHASE_ID");
// Create product array
$products = array();
$itemID = readParam("INTERNAL_PRODUCT_ID");
$quantity = 1;
if (!ONCE_PER_PURCHASED_QUANTITY)
{
$quantity = readParam("QUANTITY");
}
// Add product to the product array
$products[] = array (
"itemIdentification" => $itemID,
"quantity" => $quantity,
);
// Create the order
$order = array(
"orderIdentification" => $orderID,
"customerIdentification" => $customerID,
"comment" => $comment,
"product" => $products,
);
// Calling webservice
$ticket = doOrder($LC_Username, $LC_Password, $order);
if ($ticket)
{
Header("HTTP/1.1 200 Ok");
Header("Content-Type: text/plain");
print TICKET_URL.$result->order->ticketIdentification;
exit;
}
else
{
$error = "No result from WSConnector_doOrder";
trigger_error($error, E_USER_WARNING);
printError(500, "Internal Error.");
exit;
}
// End of Main program
?>
Now this is the code that I got and have to work with. And this is hosted on a different remote server.
I am very very new to salesforce and I am not really sure how to trigger calling this php file over a remote site.
The basic idea is:
1. New entry in Lead is created.
2. Immediately 2 fields (custID and prodID) are sent to this PHP file I have pasted above (some of the variables are different)
3. This does its processing and sends 2 fields back to salesforce.
Any help or guidance is appreciated. Even links to read up on is okay as I am completely clueless.
PS: I have another example where it makes use of JSON Messages if that may make any difference.
Thanks
I'll repost the links from my comment :)
https://salesforce.stackexchange.com/questions/23977/is-it-possible-to-get-the-record-id
Web hook in salesforce?
If your PHP endpoint is visible on the open web (not a part of some intranet or just your own localhost) then simplest thing to do would be to send an Outbound Message from Salesforce. No coding required, just some XML document you'll have to parse on the PHP side. Plus it will automatically attempt to resend the messages if the host is unreachable...
If your app can't be accessed from SF servers then I think your PHP app will have to be the "actor". Querying SF every X minutes for new Leads or maybe subscribing to Streaming API... This will mean you'd have to store credentials to SF on your PHP app and remember to either change the password periodically or set on the "integration user"'s profile the "password never expires" checkbox.
So you're getting the notification, you generate your tickets, time to send them back. Will you want to pretend the update of Lead was done by the person that created it or will you want to see "last modified by: Integration User"? Outbound message can contain session id which you can use to act as the person who initiated the action (created the lead and fired the workflow) - at least until they log out or the session timeouts.
For message back you can use SOAP or REST salesforce apis - read the docs to figure out how to send an update command (and if you want to make it clear it was done by special user associated with this PHP app - how to log in to the APIs). I think the user's profile must have "API enabled" ticked before you could reuse somebody's session so maybe it's better to have a dedicated account for integrations like that...
Another thing to keep in mind if it'd be outbound messages is to ignore the messages sent from sandboxes so if somebody makes a test environment you will not call your "production" database of tickets. You can also remember to modify the outbound message and remote site setting every time a sandbox is made so you'll have "prod talking to prod, test talking to test". I know you can include user's session id in the OM - so maybe you can also add organization's id (for production it'll stay the same, every new sandbox will have new id).
The problem with this approach is that it might not scale. If 1000 leads is inserted in one batch (for example with Data Loader) - you'll get spammed with 1000 outbound messages. Your server must be able to handle such load... but it will also mean you're using 1 API request to send every single update back. You can check the limit of API requests in Setup -> Company Information. Developer Edition will have this limit very low, sandboxes are better, production is best (it also depends how many user licenses have you bought). That's why I've asked about some batching them up.
More coding but also more reliable would be to ask SF for changes every X minutes (Streaming API? Normal query? check the "web hook" answer) and send an update of all these records in one go. SELECT Id, Name FROM Lead WHERE Ticket__c = null (note there's nothing about AND LastModifiedDate >= :lastTimeIChecked)...
I would like to create a feature for my web application that once a user is entered in my database, every 4 weeks an email is sent to them reminding them to, for example, give some feedback. I've heard cron job is what Im looking for but Im curious what else is out there, is there maybe a php script that exists or an easy way to do it?
I want something like a countdown from once they enter the database to start counting down till 4 weeks has passed then call a php file or something that sends an email of my choosing to them. if this is possible let me know! thank you
I would say to use a cron job (it could run everyday at a certain time that would be good to send an email), and the cron job could call a php script that would look through all your users and check when they signed up, and see if anyone signed up 4 weeks ago (or some multiple of that). For anyone who meets this condition, you could go through a loop and send them emails with the mail() function.
Cron Job
Log into a shell on your server and type "sudo crontab -e" and type in something like this:
30 14 * * * php path/to/some/phpscript.php
In this example, phpscript.php is going to be run at 14:30 every day (2:30 pm). But that doesn't mean it's going to email all the users every day! See the script below.
PHP Script
<?php
# get all users (or your query could choose only users who signed up (4 weeks)*n ago)
$result = mysql_query('SELECT * FROM user');
$users = array();
while($row = mysql_fetch_assoc($result)) $users[] = $row;
# loop through users and (if you didn't already check) see which ones have signed up (4 weeks)*n ago
foreach ($users as $user) {
# take the number of seconds and convert it to number of days
$today = (int)(strtotime(date('c')) / 60 / 60 / 24);
$signup_day = (int)(strtotime($user['signup_date']) / 60 / 60 / 24);
# check if the amount of days since signup is a multiple of 28 (4*7)
if (($today - $signup_day) && ($today - $signup_day) % 28 == 0) {
send_mail_to($user);
}
}
?>
I would like to automate the process of sending this email. I mean when a condition is met then the email should automatically be sent to the given email addresses which is already given as hard-coded values. So for an example in my case a Technician has to complete 40jobs a day and if he finished 35 at the end of the day an email should be sent to the supervisor(provided his email id is already given) with Subject name and the body should be like ” The Technician 1234 has completed only 35 jobs for the day instead of 40. I was wondering how can implement this as Im very new to the field of PHP. Please anyone help me out. If possible please provide me with an example.
Thanks
Dilip
You could run a cron that uses the php mail function to send a report about each programmer at a set time each day. The cron script would look something like:
<?php
$to = 'admin#mydomain.com';//the set up email to mail too
$result = mysql_query('select programmer_id, job_count, job_requirement from table'); //query the database
while($job = mysql_fetch_object($result)){
mail($to,'Job counts for ' . $job->programmer_id,"Completed $job->job_count out of $job->job_requirement jobs","FROM: jobcounter#mydomain.com");
}
Have a script check the conditions and send emails, and run it periodically: http://www.google.com/search?q=cronjob
I'm assuming here that your problem is the triggering of the event, rather than the sending of the email itself.
In the example you described, you would need to have a script run at a certain time of day that would check for any condition that would require an email sending, and then send the email. Under any unix-like system, cron is the ideal solution to this. If you are on some kind of basic shared hosting you may not be able to set this up. In that case you would need to set up a task to run on a machine that you do have control over that would call a URL that would run the PHP script. This could be a cronjob, or a Scheduled Task under Windows.
If your example was switched around so that, say, an email was to be sent as soon as a technician completed 40 jobs then you would be able to send the email as part of the script that handled the form submission from the technician whenever he completed a task.
Setup a Cron Job that runs at the "end of the day":
23 55 * * * /path/to/php /path/to/script.php
Have it run a PHP script that can query your Job Store for whatever condition you want to check. For example with Job Store being a database.
$db = new PDO(/* config */);
$result = $pdo->query(
'SELECT count(id) as "tasks_done"
FROM tasks WHERE engineer = "Tom"
AND finished_at = now()');
$result = $result->fetchAll();
if($result[0]['tasks_done'] < 40) {
mail( ... )
}
If the condition is met, send the mail. The above needs refining of course. Dont expect being able to copy/paste it.
Also see:
What is the best method for scheduled tasks in PHP
http://greenservr.com/projects/crontab/crontab.phps
you should use mail() function:
$technicianId = 1234;
$jobsNeeded = 40;
$jobsDone = getJobsDone($technicianId);
if ($jobsDone <= $jobsNeeded) {
mail('supervisor#yourcompany.com', 'Technician '.$technicianId.' slacking', 'The Technician '.$technicianId.' has completed only '.$jobsDone.' jobs for the day instead of '.$jobsNeeded);
}
Could have a cronjob that runs at the end of each day which checks what each technician has done and emails it to the manager.
How Can I find whether the transaction made by user is settled or Unsettled in the authorize.net.I am using AIM.
I want to get through coding.When the transaction is completed and I cant find transaction status.But I want to get whether it goes for settled or unsettled transaction.
Thanks in advance.
You cannot get this information through coding as no API Authorize.Net offers allows for this. It can only be done through the control panel. When you process a transaction and it is approved you can assume the transaction is unsettled. Transactions are settled once per day usually around midnight Pacific Time. After that you can assume a transaction is settled.
As of 03-16-2011 authorize.net has released two new calls to the Transaction Details API, getUnsettledTransactionList and getBatchStatistics.
getUnsettledTransactionList returns up to 1,000 unsettled transactions per call, returning the most recent transactions. The information returned in the response will be the same as what's returned in getTransactionList call.
getBatchStatistics returns the batch stats for a single batch like settlement state and time, charge count, decline count, etc.
For more info, check out the XML guide and the SOAP guide.
At the time of writing the PHP SDK is at version 1.1.6 and does not have this function built into the TD api, however if you look at the documentation provided above, as well as this example page, you will see that getting a list of unsettled transactions is in fact possible.
from this page
I've followed this link http://developer.authorize.net/api/transaction_details/ and get this code from there,
<?php
require_once "anet_php_sdk/AuthorizeNet.php";
define("AUTHORIZENET_API_LOGIN_ID", "YOURLOGIN");
define("AUTHORIZENET_TRANSACTION_KEY", "YOURKEY");
// Get Settled Batch List
$request = new AuthorizeNetTD;
$response = $request->getSettledBatchList();
echo count($response->xml->batchList->batch) . " batches\n";
foreach ($response->xml->batchList->batch as $batch) {
echo "Batch ID: " . $batch->batchId . "\n";
}
// Get Transaction Details
$transactionId = "12345";
$response = $request->getTransactionDetails($transactionId);
echo $response->xml->transaction->transactionStatus;
but I m getting this error message.
User authentication failed due to invalid authentication values.
As suggested in #cwd's answer, the most reliable way to know if a transaction is settled is to call getUnsettledTransactionList or getBatchStatistics, but you can also just check what your Transaction Cut-off Time is set to.
Log in to your Authorize.net admin, click Account > Transaction Cut-Off Time
My account is set to 4:00 PM PDT so you can just compare your transaction time to the cut off time. Something like:
$createdTime = new DateTime($charge['createdTime']);
// starting point for settle time
$settleTime = new DateTime($createdTime->format('Y-m-d') . ' 16:00:00');
$now = new DateTime();
// if card was charged after settle time for
// that day, move settle time to the next day
if ($createdTime > $settleTime) {
$settleTime->add(new DateInterval('P1D'));
}
if ($now > $settleTime) $settled = true;
http://developer.authorize.net/api/transaction_details/ is the API you are looking for.