Skip to content

Commit

Permalink
Merge branch 'trunk' into add/create-sensei-pages-on-activation
Browse files Browse the repository at this point in the history
  • Loading branch information
Imran92 authored Jan 9, 2024
2 parents 4a2c91c + b0f41a2 commit a21d890
Show file tree
Hide file tree
Showing 11 changed files with 239 additions and 5 deletions.
4 changes: 4 additions & 0 deletions changelog/fix-time-based-tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: development

Introduce Clock interface and corresponding public property for Sensei object.
2 changes: 1 addition & 1 deletion includes/class-sensei-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -2853,7 +2853,7 @@ public static function output_query_params_as_inputs( array $excluded = [], stri
*/
public static function format_last_activity_date( string $date ) {
$timezone = new DateTimeZone( 'GMT' );
$now = new DateTime( 'now', $timezone );
$now = Sensei()->clock->now( $timezone );
$date = new DateTime( $date, $timezone );
$diff_in_days = $now->diff( $date )->days;

Expand Down
21 changes: 21 additions & 0 deletions includes/class-sensei.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use Sensei\Clock\Clock;
use Sensei\Clock\Clock_Interface;
use Sensei\Internal\Action_Scheduler\Action_Scheduler;
use Sensei\Internal\Emails\Email_Customization;
use Sensei\Internal\Installer\Updates_Factory;
Expand Down Expand Up @@ -350,6 +352,13 @@ class Sensei_Main {
*/
public $action_scheduler;

/**
* Clock.
*
* @var Clock_Interface
*/
public $clock;

/**
* Constructor method.
*
Expand Down Expand Up @@ -377,6 +386,18 @@ private function __construct( $main_plugin_file_name, $args ) {
$alloptions = wp_load_alloptions();
$this->install_version = $alloptions['sensei-install-version'] ?? null;

/**
* Filter the clock.
*
* @hook sensei_clock_init
*
* @since $$next-version$$
*
* @param {Clock_Interface} $clock The clock.
* @return {Clock_Interface} Filtered clock.
*/
$this->clock = apply_filters( 'sensei_clock_init', new Clock( wp_timezone() ) );

Check warning on line 399 in includes/class-sensei.php

View check run for this annotation

Codecov / codecov/patch

includes/class-sensei.php#L399

Added line #L399 was not covered by tests

// Initialize the core Sensei functionality
$this->init();

Expand Down
25 changes: 25 additions & 0 deletions includes/clock/class-clock-interface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* File containing the Clock_Interface.
*
* @package sensei
*/

namespace Sensei\Clock;

use DateTimeZone;

/**
* Interface Clock_Interface
*
* @since $$next-version$$
*/
interface Clock_Interface {
/**
* Get the current time.
*
* @param DateTimeZone|null $timezone The timezone to use. Uses the default timezone if not provided.
* @return \DateTimeImmutable
*/
public function now( DateTimeZone $timezone = null );
}
47 changes: 47 additions & 0 deletions includes/clock/class-clock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* File containing the Clock class.
*
* @package sensei
*/

namespace Sensei\Clock;

use DateTimeZone;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Class Clock
*
* @since $$next-version$$
*/
class Clock implements Clock_Interface {
/**
* The timezone to use.
*
* @var DateTimeZone
*/
private DateTimeZone $timezone;

/**
* Clock constructor.
*
* @param DateTimeZone $timezone The timezone to use.
*/
public function __construct( DateTimeZone $timezone ) {
$this->timezone = $timezone;
}

/**
* Get the current time.
*
* @param DateTimeZone|null $timezone The timezone to use.
* @return \DateTimeImmutable
*/
public function now( DateTimeZone $timezone = null ) {
return new \DateTimeImmutable( 'now', $timezone ?? $this->timezone );
}
}
12 changes: 12 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public function __construct() {
// Enable features.
tests_add_filter( 'sensei_feature_flag_tables_based_progress', '__return_true' );

// Init clock.
tests_add_filter( 'sensei_clock_init', [ $this, 'init_clock' ] );

/*
* Load PHPUnit Polyfills for the WP testing suite.
* @see https://github.com/WordPress/wordpress-develop/pull/1563/
Expand Down Expand Up @@ -85,6 +88,14 @@ public function load_sensei() {
add_filter( 'sensei_scheduler_class', [ __CLASS__, 'scheduler_use_shim' ] );
}

public function init_clock() {
// Testing setup for clock.
require_once SENSEI_TEST_FRAMEWORK_DIR . '/class-sensei-clock-stub.php';

// Set the clock to a fixed time.
return new Sensei_Clock_Stub();
}

/**
* Scheduler: Use shim.
*
Expand Down Expand Up @@ -120,6 +131,7 @@ public function includes() {
require_once SENSEI_TEST_FRAMEWORK_DIR . '/trait-sensei-scheduler-test-helpers.php';
require_once SENSEI_TEST_FRAMEWORK_DIR . '/trait-sensei-test-redirect-helpers.php';
require_once SENSEI_TEST_FRAMEWORK_DIR . '/trait-sensei-hpps-helpers.php';
require_once SENSEI_TEST_FRAMEWORK_DIR . '/trait-sensei-clock-helpers.php';
require_once SENSEI_TEST_FRAMEWORK_DIR . '/class-sensei-background-job-stub.php';
require_once SENSEI_TEST_FRAMEWORK_DIR . '/factories/class-sensei-factory.php';
require_once SENSEI_TEST_FRAMEWORK_DIR . '/factories/class-wp-unittest-factory-for-post-sensei.php';
Expand Down
22 changes: 22 additions & 0 deletions tests/framework/class-sensei-clock-stub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
/**
* Stub for Clock_Interface.
*
* @package sensei-tests
*/

use Sensei\Clock\Clock_Interface;

/**
* Class Sensei_Clock_Stub.
*/
class Sensei_Clock_Stub implements Clock_Interface {
/**
* Get the current time. This is a stub that always returns the beginning of the Unix epoch.
*
* @return \DateTimeImmutable
*/
public function now( \DateTimeZone $timezone = null ) {
return ( new \DateTimeImmutable( '@0' ) )->setTimezone( $timezone ?? new \DateTimeZone( 'UTC' ) );
}
}
54 changes: 54 additions & 0 deletions tests/framework/trait-sensei-clock-helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* File with trait Sensei_Clock_Helpers.
*
* @package sensei-tests
*/

// phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid -- Using PHPUnit conventions.

use Sensei\Clock\Clock_Interface;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Helpers related to the clock.
*
* @since $$next-version$$
*/
trait Sensei_Clock_Helpers {

/**
* Set the clock to a specific time.
*
* @param int|int[] $timestamp The timestamp or an array of timestamp clock will return on consecutive calls.
* @param string $timezone The timezone to use. UTC by default.
*/
private function set_clock_to( $timestamp, $timezone = 'UTC' ) {
$return_values = array();

$timestamp = is_array( $timestamp ) ? $timestamp : array( $timestamp );
$timestamp = array_map( 'intval', $timestamp );

foreach ( $timestamp as $ts ) {
$return_values[] = new \DateTimeImmutable( "@$ts", new \DateTimeZone( $timezone ) );
}

$clock = $this->createMock( Clock_Interface::class );
$clock->method( 'now' )
->willReturnOnConsecutiveCalls(
...$return_values
);

Sensei()->clock = $clock;
}

/**
* Reset the clock to the default.
*/
private function reset_clock() {
Sensei()->clock = new Sensei_Clock_Stub();
}
}
34 changes: 34 additions & 0 deletions tests/unit-tests/clock/test-class-clock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace SenseiTest\Clock;

use Sensei\Clock\Clock;

/**
* Test the Clock class.
*
* @covers Sensei\Clock\Clock
*/
class Clock_Test extends \WP_UnitTestCase {
public function testNow_Always_ReturnsImmutableDateTime() {
// Arrange.
$clock = new Clock( new \DateTimeZone( 'UTC' ) );

// Act.
$now = $clock->now();

// Assert.
$this->assertInstanceOf( \DateTimeImmutable::class, $now );
}

public function testNow_DateTimeZoneGiven_ReturnsDateTimeInGivenTimeZone() {
// Arrange.
$clock = new Clock( new \DateTimeZone( 'America/New_York' ) );

// Act.
$now = $clock->now();

// Assert.
$this->assertEquals( 'America/New_York', $now->getTimezone()->getName() );
}
}
13 changes: 10 additions & 3 deletions tests/unit-tests/test-class-sensei-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
class Sensei_Utils_Test extends WP_UnitTestCase {
use \Sensei_File_System_Helper;
use \Sensei_Clock_Helpers;

/**
* Setup function.
Expand Down Expand Up @@ -286,17 +287,23 @@ public function testOutputQueryParamsAsInputs_WhenAParamIsExcluded_ReturnsCorrec
*
* @dataProvider lastActivityDateTestingData
*/
public function testFormatLastActivityDate_WhenCalled_ReturnsCorrectlyFormattedDates( $minutes_count, $expected_output ) {
public function testFormatLastActivityDate_WhenCalled_ReturnsCorrectlyFormattedDates( $seconds_count, $expected_output ) {
/* Arrange */
$gmt_time = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $minutes_count . ' seconds' ) );
$date_as_per_format = wp_date( get_option( 'date_format' ), ( new DateTime( $gmt_time ) )->getTimestamp(), new DateTimeZone( 'GMT' ) );
$current_datetime = new DateTimeImmutable( 'now', new DateTimeZone( 'GMT' ) );
$this->set_clock_to( $current_datetime->getTimestamp() );

$test_time = $current_datetime->getTimestamp() - $seconds_count;
$gmt_time = gmdate( 'Y-m-d H:i:s', $test_time );
$date_as_per_format = wp_date( get_option( 'date_format' ), $test_time, new DateTimeZone( 'GMT' ) );

/* Act */
$actual = Sensei_Utils::format_last_activity_date( $gmt_time );

/* Assert */
$expected = empty( $expected_output ) ? $date_as_per_format : $expected_output;
self::assertEquals( $expected, $actual, 'Last activity date is not being formatted correctly' );

$this->reset_clock();
}

public function testSenseiGradeQuiz_WhenCalled_UpdatesTheFinalGrade() {
Expand Down
10 changes: 9 additions & 1 deletion tests/unit-tests/test-class-sensei.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use Sensei\Installer\Installer;
use Sensei\Clock\Clock_Interface;
use Sensei\Internal\Action_Scheduler\Action_Scheduler;
use Sensei\Internal\Migration\Migration_Job_Scheduler;

Expand Down Expand Up @@ -200,6 +200,14 @@ public function testActivate_WhenSenseiIsActivated_CreatesAllSenseiPages() {
$this->assertTrue( ( (int) Sensei()->settings->get( 'course_page' ) ) > 0 );
$this->assertTrue( ( (int) Sensei()->settings->get( 'my_course_page' ) ) > 0 );
$this->assertTrue( ( (int) Sensei()->settings->get( 'course_completed_page' ) ) > 0 );
}

public function testConstructor_Always_InitializesClockProperty() {
/* Arrange. */
$sensei = Sensei();

/* Assert. */
$this->assertInstanceOf( Clock_Interface::class, $sensei->clock );
}

/**
Expand Down

0 comments on commit a21d890

Please sign in to comment.