Skip to content

Commit

Permalink
Merge branch 'trunk' into add/sfcc-token-management
Browse files Browse the repository at this point in the history
  • Loading branch information
alecgeatches authored Dec 2, 2024
2 parents 332bc36 + d73c623 commit 017c268
Show file tree
Hide file tree
Showing 32 changed files with 830 additions and 2,911 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: E2E Tests

on:
# Run on all pull requests.
pull_request:
push:
branches:
- trunk

# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the branch name for pull requests
# or the commit hash for any other events.
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
cancel-in-progress: true

jobs:
test:
name: End-to-End Testing against WordPress
runs-on: ubuntu-24.04

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Use desired version of NodeJS
uses: actions/[email protected]
with:
node-version: 20
cache: npm

- name: Npm install
run: |
npm ci
- name: Install Playwright dependencies
run: |
npx playwright install chromium --with-deps
- name: Start up WordPress environment
run: |
npm run dev:build
- name: Run E2E tests
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
run: |
npm run test:e2e
- name: Stop WordPress environment
run: |
npm run dev:stop
- name: Archive E2E results
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-results
path: artifacts
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ coverage
# Build output (only at root)
/build/

# Testing
/artifacts/
/test-results/

# Dependency directories
node_modules/

Expand Down
29 changes: 21 additions & 8 deletions bin/start
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/bin/sh

set -e
set -e # Exit immediately if any command exits with a non-zero status.

APP_MODE="$1" # "decoupled" or empty
SCRIPT_MODE=${2:-start} # "build" or "start". Default is "start".

# Set WordPress port and home URL.
PORT="${WP_ENV_PORT-8888}"
Expand All @@ -16,9 +17,6 @@ if [ "$APP_MODE" = "decoupled" ]; then
WP_HOME="${WP_ENV_HOME_URL-http://localhost:3000}"
fi

FLAGS="${WP_ENV_FLAGS---xdebug}"
WP_ADMIN="http://localhost:$PORT/wp-admin/"

cleanup() {
echo ""
echo "✊ Caught SIG signal. Stopping..."
Expand Down Expand Up @@ -97,11 +95,19 @@ start_redis() {
}

start_wordpress() {
# Enable Xdebug when starting the server in "start" mode.
FLAGS=""
if [ "$SCRIPT_MODE" = "start" ]; then
FLAGS="${WP_ENV_FLAGS---xdebug}"
fi

echo "🔼 Starting WordPress..."
WP_ENV_PORT="$PORT" npx wp-env start "$FLAGS"
}

open_browser() {
WP_ADMIN="http://localhost:$PORT/wp-admin/"

echo ""
echo "> 🌐 $WP_ADMIN"
echo "> 🔑 Username: admin"
Expand All @@ -128,8 +134,15 @@ trap 'cleanup' INT TERM
start_redis
start_wordpress
configure_wordpress
open_browser

# Start hot-reloading wp-scripts start
echo "🔼 Starting wp-scripts build process..."
npm start
if [ "$SCRIPT_MODE" = "build" ]; then
echo "🔼 Starting build process..."
npm run build
echo "🔼 Build completed."
elif [ "$SCRIPT_MODE" = "start" ]; then
open_browser

# Start hot-reloading wp-scripts start
echo "🔼 Starting build process for development..."
npm start
fi
10 changes: 4 additions & 6 deletions docs/concepts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,21 @@ Remote Data Blocks allows you to integrate remote data into posts, pages, patter

## Remote data

**Remote data** refers to data that is fetched from an external source, such as an API or a third-party service. This might be a product in your Shopify store, data in an Airtable or Google Sheet, or a file in a GitHub repository. Remote data is usually fetched via HTTP requests but you can [extend the plugin](extending.md) to support other transports.
**Remote data** refers to data that is fetched from an external source, such as an API or a third-party service. This might be a product in your Shopify store, data in an Airtable or Google Sheet, or a file in a GitHub repository. Remote data is usually fetched via HTTP requests but you can [extend the plugin](../extending/index.md) to support other transports.

## Remote data block

A **remote data block** is a custom block that fetches and displays data from a specific remote source. Each remote data block has a unique name and provides a specific kind of data.

For example, you might have a remote data block named "Shopify Product" that fetches a product from your Shopify store and displays the product's name, description, price, and image. Or, you might have a remote data block named "Conference event" that displays rows from an Airtable and displays the event's name, location, and type. It might look something like this:

[image tk]
For example, you might have a remote data block named "Shopify Product" that fetches a product from your Shopify store and displays the product's name, description, price, and image. Or, you might have a remote data block named "Conference event" that displays rows from an Airtable and displays the event's name, location, and type.

Remote data blocks are **container blocks** that contain other blocks and provide remote data to them. You retain full control over the layout, design, and content. You can leverage patterns to enable consistent styling and workflows, and you can customize the block's appearance using the block editor or `theme.json`.

Remote data blocks are custom blocks, but they are created and registered by our plugin and don't require custom block development. Remote data is loaded via [the block bindings API](https://make.wordpress.org/core/2024/03/06/new-feature-the-block-bindings-api/).

## Data sources and queries

Each remote data block is associated with a **data source** and a **query** that defines how data is fetched, processed, and displayed. Simple data sources and queries can be configured via the plugin's settings screen, while others may require custom PHP code (see [extending](extending.md)).
Each remote data block is associated with a **data source** and a **query** that defines how data is fetched, processed, and displayed. Simple data sources and queries can be configured via the plugin's settings screen, while others may require custom PHP code (see [extending](../extending/index.md)).

## Data fetching

Expand All @@ -42,4 +40,4 @@ Since remote data blocks are container blocks, you can use patterns to create re

## Technical concepts

If you're a developer and want to understand the internals of Remote Data Blocks so that you can extend its functionality, head over the [extending guide](extending.md).
If you're a developer and want to understand the internals of Remote Data Blocks so that you can extend its functionality, head over the [extending guide](../extending/index.md).
2 changes: 1 addition & 1 deletion docs/extending/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ add_filter( 'wpcomvip_log_to_query_monitor', '__return_false' );
Filter whether to register the included example API block ("Conference Event") (default: `true`).

```php
add_filter( 'remote_data_blocks_register_example_block', '__return false' );
add_filter( 'remote_data_blocks_register_example_block', '__return_false' );
```

### remote_data_blocks_allowed_url_schemes
Expand Down
2 changes: 1 addition & 1 deletion docs/extending/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Once you've defined your custom classes, you can [register a remote data block](
### Additional customization

- [Block patterns](block-patterns.md)
- [Hooks (actions and filters](hooks.md)
- [Hooks (actions and filters)](hooks.md)

## Workflows

Expand Down
10 changes: 9 additions & 1 deletion docs/extending/query.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,15 @@ The `get_input_schema` method defines the input data expected by the query. The
- `overrides` (optional): An array of possible [overrides](overrides.md) for the input variable. Each override is an associative array with the following keys:
- `type`: The type of the override. Supported values are `query_var` and `url`.
- `target`: The targeted entity for the override (e.g., the query or URL variable that contains the overridde).
- `type` (required): The type of the input variable. Supported types are `string`, `number`, and `boolean`.
- `type` (required): The type of the input variable. Supported types are:
- `base64`
- `boolean`
- `button_url`
- `image_alt`
- `image_url`
- `number`
- `price`
- `string`

#### Example

Expand Down
35 changes: 35 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Documentation

For plugin overview and getting started guide, see [README](../README.md).

## Table of Contents

- [Core Concepts](concepts/index.md)

- [Block Bindings](concepts/block-bindings.md)
- [Field Shortcodes](concepts/field-shortcodes.md)

- [Extending](extending/index.md)

- [Block Patterns](extending/block-patterns.md)
- [Block Registration](extending/block-registration.md)
- [Data Source](extending/data-source.md)
- [Hooks](extending/hooks.md)
- [Query](extending/query.md)
- [Query Runner](extending/query-runner.md)

- [Workflows](workflows/index.md)

- [Airtable Integration](workflows/airtable-with-code.md)
- [Google Sheets Integration](workflows/google-sheets-with-code.md)
- [ZIP Code Integration](workflows/zip-code-with-contract.md)

- [Development](local-development.md)
- [Troubleshooting](troubleshooting.md)
- [Releasing](releasing.md)

## Additional Documentation

- [Contributing Guidelines](../CONTRIBUTING.md)
- [Security Policy](../SECURITY.md)
- [Code of Conduct](https://make.wordpress.org/handbook/community-code-of-conduct/)
14 changes: 14 additions & 0 deletions docs/local-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ This will spin up a WordPress environment and a Valkey (Redis) instance for obje

Stop the development environment with `Ctrl+C` and resume it by running the same command. You can also manually stop the environment with `npm run stop`. Stopping the environment stops the WordPress containers but preserves their state.

### Testing

Run unit tests:

```sh
npm run test
```

For e2e tests, ensure the development environment is running, then execute:

```sh
npm run test:e2e
```

### Logs

Watch logs from the WordPress container:
Expand Down
5 changes: 3 additions & 2 deletions docs/workflows/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@

## Code-based workflows

- [Create an Airtable integration with code](workflows/airtable-with-code.md)
- [Create a Zip Code integration with code contract](workflows/zip-code-with-contract.md)
- [Create an Airtable integration with code](airtable-with-code.md)
- [Create a Google Sheets integration with code](google-sheets-with-code.md)
- [Create a Zip Code integration with code contract](zip-code-with-contract.md)
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,14 @@ public function get_request_headers( array $input_variables ): array {

public function process_response( string $html_response_data, array $input_variables ): array {
$content = $html_response_data;
$file_path = $input_variables['file_path'];
if ( '.md' === $this->default_file_extension ) {
$content = $this->update_markdown_links( $content );
$content = $this->update_markdown_links( $content, $file_path );
}

return [
'content' => $content,
'file_path' => $input_variables['file_path'],
'file_path' => $file_path,
];
}

Expand All @@ -101,9 +102,10 @@ public function process_response( string $html_response_data, array $input_varia
* - Handles URLs with fragment identifiers (e.g., '#section').
* - Removes the '.md' extension from the paths.
* @param string $html The HTML response data.
* @param string $current_file_path The current file's path.
* @return string The updated HTML response data.
*/
private function update_markdown_links( string $html ): string {
private function update_markdown_links( string $html, string $current_file_path = '' ): string {
// Load the HTML into a DOMDocument
$dom = new \DOMDocument();

Expand All @@ -125,10 +127,13 @@ private function update_markdown_links( string $html ): string {
}
$href = $node->getAttribute( 'href' );

// Check if the href is non-empty and points to a markdown file
if ( $href && preg_match( '/\.md($|#)/', $href ) ) {
// Check if the href is non-empty, points to a markdown file, and is a local path
if ( $href &&
preg_match( '/\.md($|#)/', $href ) &&
! preg_match( '/^(https?:)?\/\//', $href )
) {
// Adjust the path
$new_href = $this->adjust_markdown_file_path( $href );
$new_href = $this->adjust_markdown_file_path( $href, $current_file_path );

// Set the new href
$node->setAttribute( 'href', $new_href );
Expand All @@ -140,30 +145,55 @@ private function update_markdown_links( string $html ): string {
}

/**
* Adjusts the given path by going one level up and removes the '.md' extension.
* Adjusts the markdown file path by resolving relative paths to absolute paths.
* Preserves fragment identifiers (anchors) in the URL.
*
* @param string $path The original path.
* @param string $current_file_path The current file's path.
* @return string The adjusted path.
*/
private function adjust_markdown_file_path( string $path ): string {
private function adjust_markdown_file_path( string $path, string $current_file_path = '' ): string {
global $post;
$page_slug = $post->post_name;

// Parse the URL to separate the path and fragment
$parts = wp_parse_url( $path );

// Extract the path and fragment
$original_path = isset( $parts['path'] ) ? $parts['path'] : '';
$fragment = isset( $parts['fragment'] ) ? '#' . $parts['fragment'] : '';

// Remove leading './' or '/' but not '../'
$adjusted_path = preg_replace( '#^(\./|/)+#', '', $original_path );
// Get the directory of the current file
$current_dir = dirname( $current_file_path );

// Resolve the absolute path based on the current directory
if ( str_starts_with( $original_path, '/' ) ) {
// Already an absolute path from root, just remove leading slash
$absolute_path = ltrim( $original_path, '/' );
} else {
// Use realpath to resolve relative paths
$temp_path = $current_dir . '/' . $original_path;
$parts = explode( '/', $temp_path );
$absolute_parts = [];

foreach ( $parts as $part ) {
if ( '.' === $part || '' === $part ) {
continue;
}
if ( '..' === $part ) {
array_pop( $absolute_parts );
} else {
$absolute_parts[] = $part;
}
}

// Prepend '../' to go one level up
$adjusted_path = '../' . $adjusted_path;
$absolute_path = implode( '/', $absolute_parts );
}

// Remove the '.md' extension
$adjusted_path = preg_replace( '/\.md$/', '', $adjusted_path );
// Remove the .md extension
$absolute_path = preg_replace( '/\.md$/', '', $absolute_path );

// Reconstruct the path with fragment
return $adjusted_path . $fragment;
// Ensure the path starts with a forward slash and includes the page slug
return '/' . $page_slug . '/' . $absolute_path . $fragment;
}
}
Loading

0 comments on commit 017c268

Please sign in to comment.