Why is error_log not being called during my cron? - wordpress

I'm trying to schedule that runs every five minutes.
The code below successfully schedules the cron, and it shows up in WP Crontrol, but "Doing a cron!" never appears in the error log.
What's going wrong?
add_action('do_cron_stuff_event', 'do_cron_stuff', 10, 2);
function do_cron_stuff()
{
error_log('Doing a cron!');
}
add_filter('cron_schedules', 'cron_stuff_add_5_minute_cron_interval');
function cron_stuff_add_5_minute_cron_interval($schedules)
{
error_log("cron_stuff_add_5_minute_cron_interval called");
$schedules['five_minutes'] =
[
'interval' => 300,
'display' => esc_html__('Every Five Minutes')
];
return $schedules;
}
register_activation_hook(__FILE__, 'cron_stuff_plugin_activation');
function cron_stuff_plugin_activation()
{
error_log("cron_stuff_plugin_activation called");
if (wp_next_scheduled('do_cron_stuff_event') === false)
{
wp_schedule_event(time(), 'five_minutes', 'do_cron_stuff_event');
}
}
register_deactivation_hook(__FILE__, 'cron_stuff_plugin_deactivation');
function cron_stuff_plugin_deactivation()
{
error_log("cron_stuff_plugin_deactivation called");
wp_clear_scheduled_hook('do_cron_stuff_event');
}

It turns out that error_log actually was being called, but because it was activated by a system cron, the error log output was being sent to a different error log file than the usual one.
To fix it, I used the error_log function's third parameter to send the output to a custom log file.

I think the problem is that you're specifying 2 $accepted_args for
add_action('do_cron_stuff_event', 'do_cron_stuff', 10, 2);
while do_cron_stuff accepts none.
Change it to
add_action('do_cron_stuff_event', 'do_cron_stuff', 10);
and see if that works.

WP-Cron works by: on every page load, a list of scheduled tasks is checked to see what needs to be run. Any tasks scheduled to be run will be run during that page load. WP-Cron does not run constantly as the system cron does; it is only triggered on page load. Scheduling errors could occur if you schedule a task for 2:00PM and no page loads occur until 5:00PM.
https://developer.wordpress.org/plugins/cron/
This means that you should trigger(query) /wp-cron.php from outside every 5 minutes.

Related

Show test body, test steps for passing tests in Cypress

When tests pass in Cypress it doesn't show the steps but if fails it shows all the steps and what step caused test to fail.
I want to see passing tests body/steps too.
Below image shows a passing test and a failing test. Failing test is much more informative. I want passing test to be like that too. How can I achieve this?
it('should select shipment method and type "test" into additional
notes', function () {
cy.intercept('GET',
'**/GetDetailWithAvailableCampaign*').as('basketDetails')
cy.on('uncaught:exception', (err, runnable) => { // If CheckoutJS throws an error, it will be caught here
cy.get('[data-cy="information::forward"]').click()
cy.url().should('include', '/basket/checkout/payment')
cy.get('[data-cy="shipping::shipment_type"]').first().click()
cy.get('[data-cy="shipping::shipment_type"]').should('be.checked')
cy.get('[data-cy="misc::additional_message_checkbox"]').check({force: true}).should('be.checked')
cy.get('[data-cy="misc::additional_message_textarea"]').should('be.visible').clear().type('Test')
// there is no shipping::forward
// cy.get('[data-cy="shipping::forward"]').click()
cy.get('[data-cy="information::forward"]').click()
})
})
it('should focus iframe and put a credit card', function () {
cy.wait(4000)
cy.url().should('include', '/basket/checkout/shipping')
const iframeSelector = 'iframe[data-cy="payment::iframe"]'
getIframeBody(iframeSelector).find('.btn-card-visa').click()
cy.wait(2000)
getIframeBody(iframeSelector).find('input#CardNumber').clear().type(Cypress.env('credit_card').number)
getIframeBody(iframeSelector).find('input#Expiry').clear().type(Cypress.env('credit_card').expiry)
getIframeBody(iframeSelector).find('input#HolderName').clear().type(Cypress.env('credit_card').holder_name)
getIframeBody(iframeSelector).find('input#VerificationCode').clear().type(Cypress.env('credit_card').cvv)
getIframeBody(iframeSelector).find('.btn-next').click()
}
By default, clicking on a test's name in the runner will expand and show all steps executed. In your case, it is doing this. But the issue you are running into is most likely that the uncaught:exception event you are waiting for in the first test is not occurring, and therefore no steps are executed. If you remove the cy.on('uncaught:exception'), you'll see the steps are executed.

How to create execute function a one time using wp-cron

I create a plugin for send woocommerce data external system plugin i want create a cron run a one time like only run after plugin active success
this is i'm used cron code
add_action('wpse71941_cron', 'wpse71941_long_running');
function wpse71941_long_running($args)
{
// might need to call `set_time_limit` here
set_time_limit(0);
include 'customers.php';
include 'orders.php';
include 'products.php';
// return normal time limit
if($l = ini_get('max_execution_time'))
set_time_limit($l);
}
// schedule the event for right now
wp_schedule_single_event(
time(),
'wpse71941_cron',
array('args' => 'for', 'callback' => 'function')
);
any suggestions to send data in background process using corn or any?

How effective is it adding a logout command at the end of a test case?

I am running a test suite (test1, test2, test3) in Cypress. I noticed when I run this suite for the first time, they all pass. On the next test run, they fail. It seems that it is failing because the data from test3 has not been removed from the cypress browser when test1 begins to run. Could this be a load issue or would adding a logout command at the end of each test case be the solution? Not sure what would be the solution for this.
It seems that it is failing because the data from test3 has not been removed from the cypress browser. First step is to find out where that data being stored ex: cookie, session storage or local storage? Once you found it, you can choose appropriate method to delete data. Incase you are interested in clearing all u can do something as below
beforeEach(() => {
cy.window().then(win => win.sessionStorage.clear());
cy.clearCookies();
cy.clearLocalStorage();
});
Make sure above syntax is correct from cypress.io.
In your support/index.js or support/index.ts file, you could have a call to before(() => {} that loads your browser up once, and then have all of your tests run in one browser session. When you run the tests again, the first thing it will do is reload the page in the browser so that you have a clean session to start from.
Have you tried adding a step to clear the cookies?
Cypress.Commands.add('logout', () => {
cy.clearCookies().then(() => {
cy.getCookies().should('be.empty').visit('/')
})
});
I see 2 solutions:
I. Add an assertion for the logout command - usualy adding an assertion solves this problem.
Cypress.Commands.add("shopFE_logout", (domain) => {
cy.log('shopFE_logout - start')
cy.get('[data-qa="logoutButton"]')
.click({ force: true })
.should('not.exist')
cy.log('shopFE_logout - end')
})
II. The more secure, but not popular way - separate the test cases to be 1 per file and organize them in folders
I found this on cypress docs "Remember, Cypress already automatically clears localStorage, cookies, sessions, etc before each test. Make sure you are not trying to clean up state that is already cleaned up by Cypress automatically."
https://docs.cypress.io/guides/references/best-practices.html#Is-resetting-the-state-necessary.
I don't think adding logout before each test will be a good idea.
In my test, I do login before each test and I have not done logout and still working fine
describe('This is my test suite', () => {
let credential = "";
beforeEach(function () {
cy.visit(Cypress.env('devUrl'));
cy.fixture('data/common/loginData.json').then(loginData => {
credential = loginData;
});
})
it('This is my first testcase', () => {
cy.myLoginCommand(credential.valid.username, credential.valid.password)
objLocation.navToLocationPage()
objLocation.verifySuccessMsg('Successfully Saved')
})
it('This is my second testcase', () => {
cy.myLoginCommand(credential.valid.username, credential.valid.password)
objLocation.navToLocationPage()
objLocation.verifySuccessMsg('Successfully Updated')
})
})

Cypress - How can I run test files in order

When I press the "run all specs" button or use the run command that runs all files in Cypress it runs all test files alphabetically, so I don't want that.
I want to sort all of them with my own rules.
Let's say I have 3 steps in a chat app test.
Can connect the chat app
Can connect the chat
Can the user send a message
I want to test every step without being tied to each other.
What I mean, Testing one of their own function.
What I do is as follows
chat_app_connect.spec.js
describe('Server Connecting Test', () => {
it('Visit Server page', () => {
cy.visit('https://chat.page..');
});
it('Check welcome messages', () => {
cy.contains('Live Support');
cy.contains('Hello, Stranger');
});
it('Check URL and status of circle', () => {
// URL
cy.url()
.should('include', '/hello');
// Status Circle
cy.get('circle')
.should('have.class', 'positive');
});
});
chat_connect.spec.js
import './chat_app_connect.spec.js';
describe('Chat Connecting Test', () => {
it('Type customer name', () => {
cy.get('input')
.clear()
.type('E2E Test');
});
it('Click to the submit button', () => {
cy.get('.submit-button')
.click();
});
it('Check URL and status of circle', () => {
// URL
cy.url()
.should('equal', 'https://client.dev.octopus.chat/');
// Status Circle
cy.get('circle', { timeout: 5000 })
.should('have.class', 'positive');
});
});
chatting.spec.js
import './chat_connect.spec.js';
describe('Chatting Tests', () => {
it('Type a test message then press Enter and check the message if it sent', () => {
// Type
cy.get('#chat-message')
.clear()
.type('Hey I\'m a test message{enter}');
// Check the message
cy.get('.message-list')
.should('contain', 'Hey I\'m a test message');
});
});
as you see every test is tied to each other, and that is mean when I tried to test just catting functionality its call every test and the whole tests will be tested.
I don't know if it is the right way or not.
what should I do in this case or can it be an acceptable way
I have a particular case where I launch multiple instances of an app, rather than using fixtures or test data, I simply integrate user feedback as Cypress tests from login on forwards.
In any case, I used the specPattern config in cypress.json to set the spec file run order:
{
"baseUrl": "http://localhost:5000",
"specPattern": [
"login/*.js",
"leads/new-lead.spec.js",
"leads/leads-list.spec.js",
"leads/lead-detail.spec.js",
"leads/lead-modify.spec.js",
//...
]
}
No file numbering needed :D
The easiest solution is most likely to add a prefix to all your test files, such as:
01-chat_app_connect.spec.js
02-chat_connect.spec.js
etc.
Cypress is going to take those files in alphabetical order, which you can "trick" into your wanted behavior by using a number as a prefix.
Jean Lescure's answer was a lifesaver. We needed to run tests based on priority without having a bunch of duplicated tests or symlinks. The following worked for us in our default cypress config file:
"integrationFolder":"cypress/integration",
"testFiles": [
"high_priority_specs/**/*.js",
"medium_priority_specs/**/*.js",
"low_priority_specs/**/*.js"
]
To change the level of priority we used 3 configs files that were loaded using the cypress --configFile argument. To run the higher priority tests (smoke tests only) we used the following:
"integrationFolder":"cypress/integration",
"testFiles": [
"high_priority_specs/**/*.js"
]
Cypress does not intentionally let you do this, and for good reasons:
It's generally indicative of poor test design. Tests should not depend on the state of one another. Any test should be able to be run successfully in isolation from the rest of the test suite.
You'll never be able to take advantage of cypress' built in ability to run tests in parallel since you can't guarantee one spec will be ran after another
Here is a relevant discussion about this that gets into more detail: https://github.com/cypress-io/cypress/issues/390
However, if you decide to do this anyway, you can do it by prefixing the name of the specs with a number:
01-some-spec.js
02-alphabetically-first-spec.js
03-some-other-spec.js
In addition to #Brendan answer, if you have a nested folder structure, this approach will work as well.
01-folder-name
|
- 01-some-spec.js

how to write synced-cron job that executes 20 seconds later - SyncedCron Meteor

I want to create a synced-cron job which runs only once and the execution time will be 20 seconds later as soon as the job is created. How would I write the parser?
Meteor.setTimeout can be run on the server
If you want something that runs 20 seconds after server startup, you can do this
if(Meteor.isServer){
var job = function(){};
Meteor.startup(function(){
Meteor.setTimeout(job, 20000);
});
}
If you are set on using synced-cron, you can use SyncedCron.remove(jobName). See Advanced section of Synced Cron Docs
if(Meteor.isServer){
SyncedCron.add({
name: 'Run in 20 seconds only once',
schedule: function(parser) {
// parser is a later.parse object
return parser.text('every 20 seconds');
},
job: function() {
// do something important here
SyncedCron.remove('Run in 20 seconds only once');
}
});
Meteor.startup(function(){
SyncedCron.start();
});
}
According to the doc:
To schedule a once off (i.e not recurring) event, create a job with a
schedule like this parser.recur().on(date).fullDate();
So you can set something like parser.recur().on(new Date()+1000*20).fullDate() to execute the job once.

Resources