50 | property
6 | * Timeframe Model methods are available as $timeframe->myMethod()
7 | *
8 | * Model: Timeframe
9 | */
10 | global $templateData;
11 | $button_label = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'label-booking-button' );
12 |
13 | /** @var \CommonsBooking\Model\Location $location */
14 | $location = $templateData['location'];
15 | /** @var \CommonsBooking\Model\Item $item */
16 | $item = $templateData['item'];
17 |
18 | $permalink = add_query_arg( 'cb-location', $location->ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID
19 |
20 | $timeframes = $location->getBookableTimeframesByItem( $item->ID, true );
21 | ?>
22 |
23 | thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
24 |
41 |
--------------------------------------------------------------------------------
/templates/location-calendar-header.php:
--------------------------------------------------------------------------------
1 | thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function
8 | ?>
9 |
40 |
41 |
46 |
--------------------------------------------------------------------------------
/templates/location-single-meta.php:
--------------------------------------------------------------------------------
1 | property
6 | * location Model methods are available as $location->myMethod()
7 | */
8 |
9 | global $templateData;
10 | $location = $templateData['location'];
11 |
12 | $location_address = $location->formattedAddressOneLine();
13 | $location_contact = $location->formattedContactInfoOneLine();
14 | $pickup_instructions = $location->formattedPickupInstructions();
15 | $show_contactinfo_unconfirmed = \CommonsBooking\Settings\Settings::getOption( 'commonsbooking_options_templates', 'show_contactinfo_unconfirmed' );
16 | $text_hidden_contactinfo = \CommonsBooking\Settings\Settings::getOption( 'commonsbooking_options_templates', 'text_hidden-contactinfo' );
17 |
18 |
19 | ?>
20 |
21 |
56 |
57 |
--------------------------------------------------------------------------------
/templates/location-single.php:
--------------------------------------------------------------------------------
1 | ' . esc_html__( $bookThisItemText, 'commonsbooking' ) . '';
19 | commonsbooking_get_template_part( 'item', 'calendar-header' ); // file: item-calendar-header.php
20 | commonsbooking_get_template_part( 'timeframe', 'calendar' ); // file: timeframe-calendar.php
21 | }
22 |
23 | // Multi item view
24 | if ( array_key_exists( 'items', $templateData ) && $templateData['items'] ) {
25 | foreach ( $templateData['items'] as $item ) {
26 | $templateData['item'] = $item;
27 | commonsbooking_get_template_part( 'location', 'withitem' ); // file: location-withitem.php
28 | } // end foreach $timeframes
29 | } // $item_is_selected
30 |
31 | if ( ! array_key_exists( 'item', $templateData ) && ! array_key_exists( 'items', $templateData ) ) { ?>
32 |
33 |
39 |
40 | login or
register.', 'commonsbooking' ) ),
44 | esc_url( wp_login_url( $current_url ) ),
45 | esc_url( wp_registration_url() )
46 | );
47 | ?>
48 |
49 | property
6 | * Timeframe Model methods are available as $timeframe->myMethod()
7 | *
8 | * Model: Timeframe
9 | */
10 |
11 | use CommonsBooking\Settings\Settings;
12 | global $templateData;
13 |
14 |
15 | /** @var \CommonsBooking\Model\Location $location */
16 | $location = $templateData['location'];
17 | /** @var \CommonsBooking\Model\Item $item */
18 | $item = $templateData['item'];
19 | $button_label = Settings::getOption( 'commonsbooking_options_templates', 'label-booking-button' );
20 | $permalink = add_query_arg( 'cb-location', $location->ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID
21 |
22 |
23 | $timeframes = $item->getBookableTimeframesByLocation( $location->ID, true );
24 | ?>
25 |
26 | thumbnail( 'cb_listing_medium' ) ); // div.thumbnail is printed by function ?>
27 |
28 |
29 |
post_title ); ?>
30 |
34 |
35 | formattedBookableDate() ); ?>
36 |
37 |
40 |
41 |
42 |
45 |
--------------------------------------------------------------------------------
/templates/map-admin-page-template.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wielebenwir/commonsbooking/2f394da297c7d6394d451068f92a12beb82b6fa3/templates/map-admin-page-template.php
--------------------------------------------------------------------------------
/templates/massoperations-index.php:
--------------------------------------------------------------------------------
1 |
2 |
Mass Operations
3 |
4 |
5 |
6 |
7 |
10 | .
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/templates/shortcode-items.php:
--------------------------------------------------------------------------------
1 | property
10 | * location Model methods are available as $item->myMethod()
11 | */
12 |
13 |
14 | global $templateData;
15 | $item = new \CommonsBooking\Model\Item( $templateData['item'] );
16 | $hasTimeFrames = ( array_key_exists( 'data', $templateData ) && count( $templateData['data'] ) );
17 |
18 | // the item-not-available message (if item ist currently not available) can be defined via plugin options -> message templates
19 | $noResultText = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'item-not-available' );
20 |
21 |
22 | ?>
23 |
33 |
34 | $data ) {
41 | $location = new \CommonsBooking\Model\Location( $locationId );
42 | set_query_var( 'item', $item );
43 | set_query_var( 'location', $location );
44 | set_query_var( 'data', $data );
45 | commonsbooking_get_template_part( 'timeframe', 'withlocation' );
46 | }
47 | } // end if ($timeframes) ?>
--------------------------------------------------------------------------------
/templates/shortcode-items_table.php:
--------------------------------------------------------------------------------
1 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/templates/shortcode-locations.php:
--------------------------------------------------------------------------------
1 | property
9 | * location Model methods are available as $location->myMethod()
10 | */
11 | global $templateData;
12 | $location = new \CommonsBooking\Model\Location( $templateData['location'] );
13 |
14 | // the location without items message is shown if there are currently no available items at this location. Can be defined via plugin options -> message templates
15 | $noResultText = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'location-without-items' );
16 |
17 | ?>
18 |
25 |
26 | $data ) {
29 | $item = new \CommonsBooking\Model\Item( $itemId );
30 | set_query_var( 'item', $item );
31 | set_query_var( 'location', $location );
32 | set_query_var( 'data', $data );
33 | commonsbooking_get_template_part( 'timeframe', 'withitem' ); // file: timeframe-withlocation.php
34 | }
35 | } else {
36 | ?>
37 |
38 |
39 |
--------------------------------------------------------------------------------
/templates/timeframe-calendar-day.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | getFormattedDate( 'd' ) ); ?>
5 | getFormattedDate( 'M' ) ); ?>>
6 |
7 |
8 | $slot ) {
10 | if ( array_key_exists( 'timeframe', $slot ) && $slot['timeframe'] ) {
11 | if ( $slot['timeframe']['type'] == '2' ) {
12 | ?>
13 |
14 |
15 | {{ slot.timestart }} - {{ slot.timeend }}
16 |
17 | {% if backend != 'true' %}
18 |
29 | {% endif %}
30 |
31 |
34 |
35 |
36 | {{ slot.timestart }} - {{ slot.timeend }}
37 |
38 |
39 |
44 |
45 |
--------------------------------------------------------------------------------
/templates/timeframe-notallowed.php:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | ';
11 | if ( ! is_user_logged_in() ) {
12 | printf(
13 | '
%s',
14 | esc_url( wp_login_url() ),
15 | esc_html__( 'Login to your account', 'commonsbooking' )
16 | );
17 | }
18 | ?>
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/templates/timeframe-withitem.php:
--------------------------------------------------------------------------------
1 | ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID
6 | ?>
7 |
8 | thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
9 |
10 |
15 |
16 | ';
24 | }
25 | }
26 | ?>
27 |
28 |
29 |
32 |
--------------------------------------------------------------------------------
/templates/timeframe-withlocation.php:
--------------------------------------------------------------------------------
1 | ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID
14 | ?>
15 |
16 | thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
17 |
18 |
19 |
20 |
21 |
26 |
27 | ';
38 | }
39 | }
40 | ?>
41 |
42 |
43 |
46 |
--------------------------------------------------------------------------------
/tests/cypress/cypress.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require("cypress");
2 |
3 | module.exports = defineConfig({
4 | fixturesFolder: 'tests/cypress/fixtures',
5 | screenshotsFolder: 'tests/cypress/screenshots',
6 | videosFolder: 'tests/cypress/videos',
7 | downloadsFolder: 'tests/cypress/downloads',
8 | env: {
9 | wpAdmin:'admin',
10 | wpSubscriber: 'subscriber',
11 | wpPassword:'password',
12 | },
13 | e2e: {
14 | baseUrl: 'http://localhost:1001/',
15 | setupNodeEvents(on, config) {
16 | // implement node event listeners here
17 | },
18 | video: false,
19 | specPattern: 'tests/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
20 | supportFile: 'tests/cypress/support/e2e.js',
21 | },
22 | });
23 |
--------------------------------------------------------------------------------
/tests/cypress/e2e/admin-booking.cy.js:
--------------------------------------------------------------------------------
1 | describe('test backend booking', () => {
2 | beforeEach( function() {
3 | cy.visit( '/wp-login.php' );
4 | cy.wait( 1000 );
5 | cy.get( '#user_login' ).type( Cypress.env( "wpAdmin" ) );
6 | cy.get( '#user_pass' ).type( Cypress.env( "wpPassword" ) );
7 | cy.get( '#wp-submit' ).click();
8 | } );
9 | it('can create entirely new admin booking', () => {
10 | let today = new Date()
11 | let inTwoDays = new Date()
12 | inTwoDays.setDate(today.getDate() + 2)
13 | const expectedStartDate = today.toLocaleDateString()
14 | const expectedEndDate = inTwoDays.toLocaleDateString()
15 | cy.visit('/wp-admin/post-new.php?post_type=cb_booking')
16 | cy.get('#title').type('Test booking')
17 | //TODO: get this data from fixtures
18 | cy.get('#item-id').select('BasicTest - NoAdmin')
19 | //make sure, that the correct location is automatically selected, 32 is the id of the location
20 | cy.get('#location-id').should('have.value','32')
21 | //the checkbox should be checked because the timeframe is a full-day timeframe
22 | cy.get('#full-day').should('be.checked')
23 | cy.get('#repetition-start_date').clear().type(expectedStartDate).type('{esc}');
24 | cy.get('#repetition-end_date').clear().type(expectedEndDate).type('{esc}');
25 | //click post button
26 | cy.get('#cb-submit-booking').click()
27 | cy.get('#message > p').contains('Post updated.')
28 | cy.get('#post-status-display').contains('Confirmed')
29 |
30 | //let's go to the frontend booking calendar and check that our item exists there
31 | //set date to today (this is probably unnecessary, but just to be sure)
32 | cy.clock(today.getTime())
33 | cy.visit('/?cb_item=basictest-noadmin&cb-location=32')
34 | cy.get('.is-today').should('have.class', 'is-booked')
35 | })
36 |
37 | after( function () {
38 | cy.visit('/wp-admin/edit.php?post_type=cb_booking')
39 | cy.get('.submitdelete').click({multiple: true, force: true})
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/tests/cypress/e2e/cpt-frontend-pages.cy.js:
--------------------------------------------------------------------------------
1 | describe('check load of CPT frontend pages where available', () => {
2 | const testName = 'BasicTest'
3 | it('loads items', () => {
4 | cy.visit('/?cb_item=basictest-noadmin')
5 | //wait so that the tile layer for the location map can load before taking the screenshot
6 | cy.wait(2000)
7 | cy.screenshot('cb-item-template')
8 | cy.get('.entry-title').contains(testName);
9 | //Check that location is correctly assigned
10 | cy.get('.cb-title > a').contains(testName);
11 | cy.get('.cb-timeframe-calendar').should('be.visible');
12 | cy.get('#cb_locationview_map').should('be.visible')
13 | cy.get('#cb_locationview_map').scrollIntoView().screenshot('cb-itemtemplate-locationview-map')
14 | })
15 | it ('loads locations', () => {
16 | cy.visit('/?cb_location=basictest-koln-dom-locmap-noadmin')
17 | //wait so that the tile layer for the location map can load before taking the screenshot
18 | cy.wait(2000)
19 | cy.screenshot('cb-location-template')
20 | cy.get('.entry-title').contains(testName);
21 | //check for location map
22 | cy.get('#cb_locationview_map').should('be.visible')
23 | cy.get('#cb_locationview_map').scrollIntoView().screenshot('cb-locationtemplate-locationview-map')
24 | //check address
25 | cy.get('.cb-location-address > :nth-child(2)').contains("Domkloster 4, 50667 Köln")
26 | //check item
27 | cy.get('.cb-title').contains(testName);
28 | //timeframe calendar is visible because there is only one assigned location
29 | cy.get('.cb-timeframe-calendar').should('be.visible');
30 | } )
31 | })
32 |
--------------------------------------------------------------------------------
/tests/cypress/fixtures/bookableItems.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": [
3 | {
4 | "post_id": 30,
5 | "post_title": "BasicTest – NoAdmin",
6 | "post_name": "basictest-noadmin",
7 | "test_name": "BasicTest"
8 | },
9 | {
10 | "post_id": 38,
11 | "post_title": "WeeklyRepetition NoOverbooking – NoAdmin",
12 | "post_name": "weeklyrepetition-noadmin",
13 | "test_name": "WeeklyRepetition NoOverbooking"
14 | },
15 | {
16 | "post_id": 45,
17 | "post_title": "WeeklyRepetition Overbooking CountAll- NoAdmin",
18 | "post_name": "weeklyrepetition-overbooking-noadmin",
19 | "test_name": "WeeklyRepetition Overbooking CountAll"
20 | },
21 | {
22 | "post_id": 55,
23 | "post_title": "WeeklyRepetition Overbooking CountOne – NoAdmin",
24 | "post_name": "weeklyrepetition-overbooking-countone-noadmin",
25 | "test_name": "WeeklyRepetition Overbooking CountOne"
26 | },
27 | {
28 | "post_id": 59,
29 | "post_title": "DailyRep Holiday NoOverbooking – NoAdmin",
30 | "post_name": "dailyrep-holiday-nooverbooking-noadmin",
31 | "test_name": "DailyRep Holiday NoOverbooking"
32 | },
33 | {
34 | "post_id": 71,
35 | "post_title": "DailyRep Holiday Overbooking CountAll- NoAdmin",
36 | "post_name": "dailyrep-holiday-overbooking-countall-noadmin",
37 | "test_name": "DailyRep Holiday Overbooking CountAll"
38 | },
39 | {
40 | "post_id": 79,
41 | "post_title": "DailyRep Holiday Overbooking CountOne- NoAdmin",
42 | "post_name": "dailyrep-holiday-overbooking-countone-noadmin",
43 | "test_name": "DailyRep Holiday Overbooking CountOne"
44 | },
45 | {
46 | "post_id": 90,
47 | "post_title": "WeeklyRepetition Overbooking NoCount - NoAdmin",
48 | "post_name": "weeklyrepetition-overbooking-nocount-noadmin",
49 | "test_name": "WeeklyRepetition Overbooking NoCount"
50 | },
51 | {
52 | "post_id": 118,
53 | "post_title": "DailyRep Holiday NoOverbooking 1Day – NoAdmin",
54 | "post_name": "dailyrep-holiday-nooverbooking-1day-noadmin",
55 | "test_name": "DailyRep Holiday NoOverbooking 1Day"
56 | },
57 | {
58 | "post_id": 112,
59 | "post_title": "WeeklyRepetition NoOverbooking 1Day – NoAdmin",
60 | "post_name": "weeklyrepetition-nooverbooking-1day-noadmin",
61 | "test_name": "WeeklyRepetition NoOverbooking 1Day"
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/tests/cypress/fixtures/bookableLocations.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": [
3 | {
4 | "post_id": 32,
5 | "post_title": "BasicTest – Köln Dom LocMap NoAdmin",
6 | "post_name": "basictest-koln-dom-locmap-noadmin",
7 | "test_name": "BasicTest"
8 | },
9 | {
10 | "post_id": 39,
11 | "post_title": "WeeklyRepetition NoOverbooking – NoAdmin; NoGeo",
12 | "post_name": "weeklyrepetition-nooverbooking-noadmin-nogeo",
13 | "test_name": "WeeklyRepetition NoOverbooking"
14 | },
15 | {
16 | "post_id": 47,
17 | "post_title": "WeeklyRepetition Overbooking CountAll – NoAdmin; NoGeo",
18 | "post_name": "weeklyrepetition-overbooking-countall-noadmin-nogeo",
19 | "test_name": "WeeklyRepetition Overbooking CountAll"
20 | },
21 | {
22 | "post_id": 53,
23 | "post_title": "WeeklyRepetition Overbooking CountOne – NoAdmin ; NoGeo",
24 | "post_name": "weeklyrepetition-overbooking-countone-noadmin-nogeo",
25 | "test_name": "WeeklyRepetition Overbooking CountOne"
26 | },
27 | {
28 | "post_id": 61,
29 | "post_title": "DailyRep Holiday NoOverbooking – NoAdmin; NoGeo",
30 | "post_name": "dailyrep-holiday-nooverbooking-noadmin-nogeo",
31 | "test_name": "DailyRep Holiday NoOverbooking"
32 | },
33 | {
34 | "post_id": 73,
35 | "post_title": "DailyRep Holiday Overbooking CountAll – NoAdmin; NoGeo",
36 | "test_name": "DailyRep Holiday Overbooking CountAll"
37 | },
38 | {
39 | "post_id": 81,
40 | "post_title": "DailyRep Holiday Overbooking CountOne- NoAdmin; NoGeo",
41 | "post_name": "dailyrep-holiday-overbooking-countone-noadmin-nogeo",
42 | "test_name": "DailyRep Holiday Overbooking CountOne"
43 | },
44 | {
45 | "post_id": 88,
46 | "post_title": "WeeklyRepetition Overbooking NoCount – NoAdmin; NoGeo",
47 | "post_name": "weeklyrepetition-overbooking-nocount-noadmin-nogeo",
48 | "test_name": "WeeklyRepetition Overbooking NoCount"
49 | },
50 | {
51 | "post_id": 116,
52 | "post_title": "DailyRep Holiday NoOverbooking 1Day – NoAdmin; NoGeo",
53 | "post_name": "dailyrep-holiday-nooverbooking-1day-noadmin-nogeo",
54 | "test_name": "DailyRep Holiday NoOverbooking 1Day"
55 | },
56 | {
57 | "post_id": 110,
58 | "post_title": "WeeklyRepetition NoOverbooking 1Day – NoAdmin; NoGeo",
59 | "post_name": "weeklyrepetition-nooverbooking-1day-noadmin-nogeo",
60 | "test_name": "WeeklyRepetition NoOverbooking 1Day"
61 | }
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/tests/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
--------------------------------------------------------------------------------
/tests/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/e2e.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 | Cypress.on('uncaught:exception', (err, runnable) => {
22 | // WordPress is throwing this error in the latest trunk when trying to login with a changed date #61224 in Trac. This workaround is in place until the issue is resolved
23 | if (err.message.includes('Cannot read properties of undefined (reading \'serialize\')')) {
24 | return false
25 | }
26 |
27 | // #1632
28 | if (err.message.includes('Cannot destructure property \'documentElement\' of \'o\' as it is null.')) {
29 | return false
30 | }
31 | // we still want to ensure there are no other unexpected
32 | // errors, so we let them fail the test
33 | })
34 |
--------------------------------------------------------------------------------
/tests/cypress/wordpress-files/e2e-override.json:
--------------------------------------------------------------------------------
1 | {
2 | "phpVersion": "VERSION_PLACEHOLDER",
3 | "plugins": [
4 | "./build/commonsbooking",
5 | "https://downloads.wordpress.org/plugin/wordpress-importer.zip",
6 | "https://downloads.wordpress.org/plugin/disable-welcome-messages-and-tips.zip"
7 | ],
8 | "themes": [
9 | "flegfleg/kasimir-theme"
10 | ],
11 | "env": {
12 | "tests": {
13 | "mappings": {
14 | "wp-content/plugins/commonsbooking": "./build/commonsbooking",
15 | "wp-content/plugins/commonsbooking/tests/cypress/wordpress-files": "./tests/cypress/wordpress-files"
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/php/API/AvailabilityRouteEmptyTest.php:
--------------------------------------------------------------------------------
1 | ENDPOINT );
17 |
18 | $response = rest_do_request( $request );
19 |
20 | $this->assertSame( 200, $response->get_status() );
21 | $this->assertSame( 0, count( $response->get_data()->availability ) );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/php/API/CB_REST_Route_UnitTestCase.php:
--------------------------------------------------------------------------------
1 | assertNotNull( $this->ENDPOINT );
14 | $routes = $this->server->get_routes();
15 | $this->assertArrayHasKey( $this->ENDPOINT, $routes );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/php/API/CB_REST_UnitTestCase.php:
--------------------------------------------------------------------------------
1 | server = $wp_rest_server = new \WP_REST_Server();
26 |
27 | // Enables api
28 | Settings::updateOption( 'commonsbooking_options_api', 'api-activated', 'on' );
29 | Settings::updateOption( 'commonsbooking_options_api', 'apikey_not_required', 'on' );
30 |
31 | // Registers routes (via rest_api_init hook)
32 | ( new Plugin() )->initRoutes();
33 |
34 | // Applies hook
35 | do_action( 'rest_api_init' );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/php/API/GBFS/DiscoveryRouteTest.php:
--------------------------------------------------------------------------------
1 | setStreetName( 'Karl-Marx-Straße' )
25 | ->setStreetNumber( '1' )
26 | ->setPostalCode( '12043' )
27 | ->setLocality( 'Berlin' )
28 | ->setCountry( 'Germany' )
29 | ->setCoordinates( 52.4863573, 13.4247667 );
30 |
31 | return $location->build();
32 | }
33 |
34 | /**
35 | * This can be used to get mocked locations from nominatim
36 | *
37 | * @param TestCase $case
38 | *
39 | * @return void
40 | */
41 | public static function setUpGeoHelperMock( TestCase $case ): void {
42 |
43 | $sut = $case->createStub( GeoCodeService::class );
44 | $sut->method( 'getAddressData' )
45 | ->willReturn( self::mockedLocation() );
46 | GeoHelper::setGeoCodeServiceInstance( $sut );
47 | }
48 |
49 | public function testThatGeoCoding_worksOffline() {
50 | $address = GeoHelper::getAddressData( 'Karl-Marx-Straße 1, 12043 Berlin' );
51 | $this->assertThatKarlMarxLocationIsProperlyGeoCoded( $address );
52 | }
53 |
54 | public function testThatGeoCoding_worksOnline() {
55 | GeoHelper::resetGeoCoder();
56 |
57 | $address = GeoHelper::getAddressData( 'Karl-Marx-Straße 1, 12043 Berlin' );
58 | $this->assertThatKarlMarxLocationIsProperlyGeoCoded( $address );
59 | }
60 | private function assertThatKarlMarxLocationIsProperlyGeoCoded( Location $address ): void {
61 | $this->assertEquals( 'Karl-Marx-Straße', $address->getStreetName() );
62 | $this->assertEquals( '1', $address->getStreetNumber() );
63 | $this->assertEquals( '12043', $address->getPostalCode() );
64 | $this->assertEquals( 'Berlin', $address->getLocality() );
65 | $this->assertEquals( 'Germany', $address->getCountry() );
66 | // This won't check exact coords on purpose, because sometimes there are different results
67 | $this->assertStringStartsWith( '52.4863', '' . $address->getCoordinates()->getLatitude() );
68 | $this->assertStringStartsWith( '13.424', '' . $address->getCoordinates()->getLongitude() );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/tests/php/Messages/BookingReminderMessageTest.php:
--------------------------------------------------------------------------------
1 | bookingId, 'pre-booking-reminder' );
21 | $bookingMessage->sendMessage();
22 | $mailer = $this->getMockMailer();
23 | $this->assertEmpty( $mailer->ErrorInfo );
24 | $this->assertEquals( self::FROM_MAIL, $mailer->From );
25 | $this->assertEquals( self::FROM_NAME, $mailer->FromName );
26 | $this->assertEmpty( $mailer->getBccAddresses() );
27 | $this->assertEquals( $expectedSubject, $mailer->Subject );
28 | $this->assertEquals( $expectedBody, $mailer->Body );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/php/Model/BookablePostTest.php:
--------------------------------------------------------------------------------
1 | assertTrue( $this->locationModel->isBookable() );
22 |
23 | // now the same for an item
24 | $this->assertTrue( $this->itemModel->isBookable() );
25 | }
26 |
27 | public function testGetBookableTimeframes() {
28 | ClockMock::freeze( new \DateTime( self::CURRENT_DATE ) );
29 | // test basic getting with just one bookable timeframe for a location
30 | $bookableTimeframes = $this->locationModel->getBookableTimeframes( true );
31 | $this->assertEquals( 1, count( $bookableTimeframes ) );
32 | $this->assertEquals( $this->timeframeModel, $bookableTimeframes[0] );
33 |
34 | // now the same for an item
35 | $bookableTimeframes = $this->itemModel->getBookableTimeframes( true );
36 | $this->assertEquals( 1, count( $bookableTimeframes ) );
37 | $this->assertEquals( $this->timeframeModel, $bookableTimeframes[0] );
38 |
39 | // now we create more than one item + timeframe for the first location and check if we get both
40 | $item2 = new Item( $this->createItem( 'Item2', 'publish' ) );
41 | $timeframe2 = new Timeframe( $this->createBookableTimeFrameIncludingCurrentDay( $this->locationId, $item2->ID ) );
42 |
43 | $bookableTimeframes = $this->locationModel->getBookableTimeframes( true );
44 | $this->assertEquals( 2, count( $bookableTimeframes ) );
45 | $this->assertEquals( $this->timeframeModel, $bookableTimeframes[0] );
46 | $this->assertEquals( $timeframe2, $bookableTimeframes[1] );
47 |
48 | // and now let's test if we can get the specific timeframe for just one item for the location
49 | $bookableTimeframes = $this->locationModel->getBookableTimeframes( true, [], [ $item2->ID ] );
50 | $this->assertEquals( 1, count( $bookableTimeframes ) );
51 | $this->assertEquals( $timeframe2, $bookableTimeframes[0] );
52 | }
53 |
54 | protected function setUp(): void {
55 | parent::setUp();
56 |
57 | $this->timeframeId = $this->createBookableTimeFrameIncludingCurrentDay();
58 | $this->locationModel = new Location( $this->locationId );
59 | $this->itemModel = new Item( $this->itemId );
60 | $this->timeframeModel = new Timeframe( $this->timeframeId );
61 | }
62 |
63 | protected function tearDown(): void {
64 | parent::tearDown();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tests/php/Model/ItemTest.php:
--------------------------------------------------------------------------------
1 | timeframeModel;
23 | $this->assertEquals($timeframeArray, $this->itemModel->getBookableTimeframesByItem($this->locationId)); //Not working
24 | }
25 | */
26 |
27 | public function testGetAdmins() {
28 | // Case: No admins
29 | // $this->assertEquals([], $this->itemModel->getAdmins()); - Currently this function includes the post author
30 | $this->assertEquals( [ self::USER_ID ], $this->itemModel->getAdmins() );
31 |
32 | // Case: CB Manager as admin
33 | $this->createCBManager();
34 | $adminItemModel = new Item(
35 | $this->createItem( 'Testitem2', 'publish', [ $this->cbManagerUserID ] )
36 | );
37 | // $this->assertEquals([$this->cbManagerUserID], $adminItemModel->getAdmins()); - Currently this function includes the post author
38 | $this->assertEquals( [ $this->cbManagerUserID, self::USER_ID ], $adminItemModel->getAdmins() );
39 | }
40 |
41 |
42 | /**
43 | * Can be used after PR #1179 is merged
44 | * @return void
45 | * @throws \Exception
46 | */
47 | /*
48 | public function testGetRestrictions() {
49 | $this->restrictionIds = array_unique($this->restrictionIds);
50 | $restrictionArray = [];
51 | foreach ($this->restrictionIds as $restrictionId) {
52 | $restrictionArray[] = new Restriction($restrictionId);
53 | }
54 | $this->assertEquals($restrictionArray, $this->itemModel->getRestrictions());
55 | }
56 | */
57 |
58 | protected function setUp(): void {
59 | parent::setUp();
60 | $this->restrictionIds[] = $this->createRestriction(
61 | Restriction::META_HINT,
62 | $this->locationId,
63 | $this->itemId,
64 | strtotime( self::CURRENT_DATE ),
65 | null
66 | );
67 | $this->timeframeModel = new Timeframe( $this->createBookableTimeFrameIncludingCurrentDay() );
68 | $this->itemModel = new Item( $this->itemId );
69 | $this->createSubscriber();
70 | }
71 |
72 | protected function tearDown(): void {
73 | parent::tearDown();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tests/php/Model/MessageRecipientTest.php:
--------------------------------------------------------------------------------
1 | assertEquals( 'testmail@example.com', $this->manualRecipient->getEmail() );
15 | }
16 |
17 | public function testGetNiceName() {
18 | $this->assertEquals( 'Test User', $this->manualRecipient->getNiceName() );
19 | }
20 |
21 | public function testFromUser() {
22 | $recipient = MessageRecipient::fromUser( $this->subscriber );
23 | $this->assertEquals( 'a@a.de', $recipient->getEmail() );
24 | $this->assertEquals( 'normaluser', $recipient->getNiceName() );
25 | }
26 |
27 | protected function setUp(): void {
28 | parent::setUp();
29 | $this->manualRecipient = new MessageRecipient( 'testmail@example.com', 'Test User' );
30 |
31 | $this->createSubscriber();
32 | $this->subscriber = get_userdata( $this->subscriberId );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/php/Model/WeekTest.php:
--------------------------------------------------------------------------------
1 | week = new Week( 2023, 120 );
19 | $this->assertEquals( 7, count( $this->week->getDays() ) );
20 | $this->assertEquals(
21 | array(
22 | new Day( '2023-05-01' ),
23 | new Day( '2023-05-02' ),
24 | new Day( '2023-05-03' ),
25 | new Day( '2023-05-04' ),
26 | new Day( '2023-05-05' ),
27 | new Day( '2023-05-06' ),
28 | new Day( '2023-05-07' ),
29 | ),
30 | $this->week->getDays()
31 | );
32 | }
33 |
34 | public function testGetDays2() {
35 | $this->week = new Week( 2023, 121 );
36 | $this->assertEquals( 6, count( $this->week->getDays() ) );
37 | $this->assertEquals(
38 | array(
39 | new Day( '2023-05-02' ),
40 | new Day( '2023-05-03' ),
41 | new Day( '2023-05-04' ),
42 | new Day( '2023-05-05' ),
43 | new Day( '2023-05-06' ),
44 | new Day( '2023-05-07' ),
45 | ),
46 | $this->week->getDays()
47 | );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/php/PluginTest.php:
--------------------------------------------------------------------------------
1 | assertIsArray( Plugin::getCustomPostTypes() );
16 | // make sure, that we also have a model for each custom post type
17 | foreach ( Plugin::getCustomPostTypes() as $customPostType ) {
18 | // first, create a post of this type
19 | $post = wp_insert_post(
20 | [
21 | 'post_type' => $customPostType,
22 | 'post_title' => 'Test ' . $customPostType,
23 | 'post_status' => 'publish',
24 | ]
25 | );
26 | $this->assertIsInt( $post );
27 | $this->postIDs[] = $post;
28 | // then, try to get a model from the post. Every declared CPT should have a model
29 | $this->assertInstanceOf( CustomPost::class, CustomPostType::getModel( $post ) );
30 | }
31 | }
32 |
33 | protected function setUp(): void {
34 | parent::setUp();
35 | }
36 |
37 | protected function tearDown(): void {
38 | foreach ( $this->postIDs as $postID ) {
39 | wp_delete_post( $postID, true );
40 | }
41 | parent::tearDown();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/php/Repository/CB1Test.php:
--------------------------------------------------------------------------------
1 | timeframeInstanceId = parent::createBookableTimeFrameIncludingCurrentDay();
17 |
18 | // Setup CB 2 Timeframe with CB 1 ID == 1
19 | update_post_meta( $this->timeframeInstanceId, '_cb_cb1_post_post_ID', 1 );
20 |
21 | // Setup CB 2 Location with CB 1 ID == 2
22 | update_post_meta( $this->locationId, '_cb_cb1_post_post_ID', 2 );
23 |
24 | // Setup CB 2 Item with CB 1 ID == 3
25 | update_post_meta( $this->itemId, '_cb_cb1_post_post_ID', 3 );
26 | }
27 |
28 | protected function tearDown(): void {
29 | parent::tearDown();
30 | }
31 |
32 | public function testGetCB2TimeframeId() {
33 | $this->assertTrue( CB1::getCB2TimeframeId( 1 ) == $this->timeframeInstanceId );
34 | }
35 |
36 | public function testGetCB2LocationId() {
37 | $this->assertTrue( CB1::getCB2LocationId( 2 ) == $this->locationId );
38 | }
39 |
40 | public function testGetCB2PostIdByCB1Id() {
41 | $this->assertTrue( CB1::getCB2PostIdByCB1Id( 1 ) == $this->timeframeInstanceId );
42 | $this->assertTrue( CB1::getCB2PostIdByCB1Id( 2 ) == $this->locationId );
43 | $this->assertTrue( CB1::getCB2PostIdByCB1Id( 3 ) == $this->itemId );
44 | }
45 |
46 | public function testGetCB2ItemId() {
47 | $this->assertTrue( CB1::getCB2ItemId( 3 ) == $this->itemId );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/php/Repository/ItemTest.php:
--------------------------------------------------------------------------------
1 | createTimeframe(
15 | $this->locationId,
16 | $this->itemId,
17 | strtotime( 'midnight' ),
18 | strtotime( '+90 days' )
19 | );
20 | }
21 |
22 | public function testGetByLocation(): void {
23 | $this->assertEquals(
24 | [ $this->itemId ],
25 | array_map(
26 | fn( $item ) => $item->ID,
27 | Item::getByLocation( $this->locationId, true )
28 | )
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/php/Repository/LocationTest.php:
--------------------------------------------------------------------------------
1 | createTimeframe(
15 | $this->locationId,
16 | $this->itemId,
17 | strtotime( 'midnight' ),
18 | strtotime( '+90 days' )
19 | );
20 | }
21 |
22 | public function testGetByItem() {
23 | $this->assertTrue( count( Location::getByItem( $this->itemId, true ) ) == 1 );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/php/Repository/RestrictionTest.php:
--------------------------------------------------------------------------------
1 | locationId ], [ $this->itemId ] );
26 | $this->assertIsArray( $restrictions );
27 | $this->assertEquals( 1, count( $restrictions ) );
28 | $this->assertEquals( $this->restrictionId, $restrictions[0]->ID );
29 | }
30 |
31 |
32 |
33 | protected function setUp(): void {
34 | parent::setUp();
35 | $this->timeframeId = $this->createBookableTimeFrameIncludingCurrentDay();
36 | $this->restrictionId = $this->createRestriction(
37 | 'hint',
38 | $this->locationId,
39 | $this->itemId,
40 | strtotime( self::CURRENT_DATE ),
41 | strtotime( '+1 day', strtotime( self::CURRENT_DATE ) )
42 | );
43 | }
44 |
45 | protected function tearDown(): void {
46 | parent::tearDown();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/php/Service/BookingTest.php:
--------------------------------------------------------------------------------
1 | createBooking(
11 | $this->locationId,
12 | $this->itemId,
13 | strtotime( 'midnight', strtotime( self::CURRENT_DATE ) ),
14 | strtotime( '+2 days', strtotime( self::CURRENT_DATE ) ),
15 | '8:00 AM',
16 | '12:00 PM',
17 | 'unconfirmed'
18 | );
19 | // first, we check if the cleanup will delete our freshly created unconfirmed booking (it should not)
20 | Booking::cleanupBookings();
21 | $this->assertNotNull( get_post( $bookingId ) );
22 |
23 | // we make the post 11 minutes old, so that the cleanup function will delete it (the cleanup function only deletes bookings older than 10 minutes)
24 | wp_update_post(
25 | [
26 | 'ID' => $bookingId,
27 | 'post_date' => date( 'Y-m-d H:i:s', strtotime( '-11 minutes' ) ),
28 | ]
29 | );
30 |
31 | // now we run the cleanup function again
32 | Booking::cleanupBookings();
33 |
34 | // and check if the post is still there
35 | $this->assertNull( get_post( $bookingId ) );
36 | }
37 |
38 | protected function setUp(): void {
39 | parent::setUp();
40 | $this->firstTimeframeId = $this->createBookableTimeFrameIncludingCurrentDay();
41 | }
42 |
43 | protected function tearDown(): void {
44 | parent::tearDown();
45 | \Mockery::close();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/php/Service/HolidayTest.php:
--------------------------------------------------------------------------------
1 | ', $selectOptions );
16 | // filter out the empty string after the last
17 | $selectOptions = array_filter( $selectOptions, fn( $option ) => ! empty( $option ) );
18 | // 2022 + 2 years
19 | $this->assertCount( 3, $selectOptions );
20 | $this->assertStringContainsString( '2022', $selectOptions[0] );
21 | $this->assertStringContainsString( '2023', $selectOptions[1] );
22 | $this->assertStringContainsString( '2024', $selectOptions[2] );
23 | }
24 |
25 | public function testGetStatesOption() {
26 | $selectOptions = Holiday::getStatesOption();
27 | $selectOptions = explode( '', $selectOptions );
28 | // filter out the empty string after the last
29 | $selectOptions = array_filter( $selectOptions, fn( $option ) => ! empty( $option ) );
30 | // 16 states + bund
31 | $this->assertCount( 17, $selectOptions );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tests/php/Service/iCalendarTest.php:
--------------------------------------------------------------------------------
1 | calendar->addBookingEvent(
18 | $this->bookingModel,
19 | static::$eventTitle,
20 | static::$eventDescription
21 | );
22 | $this->assertNotNull( $this->calendar->getCalendarData() );
23 | $calendarData = $this->calendar->getCalendarData();
24 | $this->checkCalendarStringValid( $calendarData );
25 | }
26 |
27 | public function testAddEventOneDay() {
28 | // tests the generic event adding method
29 | // test just for one day:
30 | $event = $this->calendar->addEvent(
31 | DateTimeImmutable::createFromFormat( 'Y-m-d', '2020-01-01' ),
32 | static::$eventTitle,
33 | static::$eventDescription
34 | );
35 | $this->assertInstanceOf( \Eluceo\iCal\Domain\Entity\Event::class, $event );
36 | $calendarData = $this->calendar->getCalendarData();
37 | $this->checkCalendarStringValid( $calendarData );
38 | }
39 |
40 | public function testAddEventMultipleDays() {
41 | $event = $this->calendar->addEvent(
42 | [ new \DateTimeImmutable( '2020-01-01 00:00:00' ),new \DateTimeImmutable( '2020-01-02 01:00:00' ) ],
43 | static::$eventTitle,
44 | static::$eventDescription,
45 | true
46 | );
47 | $this->assertInstanceOf( \Eluceo\iCal\Domain\Entity\Event::class, $event );
48 | $calendarData = $this->calendar->getCalendarData();
49 | $this->checkCalendarStringValid( $calendarData );
50 | }
51 |
52 | private function checkCalendarStringValid( string $calendar ) {
53 | $iCalendarArray = explode( "\r\n", $calendar );
54 | $iCalendarArray = array_filter( $iCalendarArray );
55 | $this->assertIsArray( $iCalendarArray );
56 |
57 | $this->assertEquals( 'BEGIN:VCALENDAR', $iCalendarArray[0] );
58 | $this->assertEquals( 'END:VCALENDAR', end( $iCalendarArray ) );
59 | }
60 |
61 | protected function setUp(): void {
62 | parent::setUp();
63 | $this->calendar = new iCalendar();
64 | $this->bookingModel = new Booking( $this->bookingId );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tests/php/Settings/SettingsTest.php:
--------------------------------------------------------------------------------
1 | assertEquals( $emailHeaderExpected, $emailBodyActual );
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/php/View/BookingTest.php:
--------------------------------------------------------------------------------
1 | createBooking(
14 | $this->locationId,
15 | $this->itemId,
16 | time() - 86400,
17 | time() + 86400
18 | );
19 | }
20 |
21 | protected function tearDown(): void {
22 | parent::tearDown();
23 | }
24 |
25 | public function testGetBookingListData() {
26 | wp_set_current_user( self::USER_ID );
27 | $bookings = Booking::getBookingListData();
28 | $this->assertTrue( $bookings['total'] == 1 );
29 |
30 | // check for #1802, delete location. Booking list should still generate
31 | wp_delete_post( $this->locationId, true );
32 | $bookings = Booking::getBookingListData();
33 | $this->assertTrue( $bookings['total'] == 1 );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/php/View/MassOperationsTest.php:
--------------------------------------------------------------------------------
1 | assertTrue( $doc->loadHTML( $html ) );
19 | $this->assertEquals( 0, count( libxml_get_errors() ) );
20 | }
21 |
22 | public function testRenderBookingViewTable() {
23 | // first with empty result
24 | ob_start();
25 | MassOperations::renderBookingViewTable( [] );
26 | $html = ob_get_clean();
27 | $this->assertStringContainsString( '
No bookings found.
', $html );
28 |
29 | // then with a booking
30 | $booking = new Booking( $this->createConfirmedBookingEndingToday() );
31 | ob_start();
32 | MassOperations::renderBookingViewTable( [ $booking ] );
33 | $html = ob_get_clean();
34 | // naive way of testing html validity
35 | libxml_use_internal_errors( true );
36 | $doc = new \DOMDocument();
37 | $this->assertTrue( $doc->loadHTML( $html ) );
38 | $this->assertEquals( 0, count( libxml_get_errors() ) );
39 | }
40 |
41 | protected function setUp(): void {
42 | parent::setUp();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/php/bootstrap.php:
--------------------------------------------------------------------------------
1 |