verbb / consume

A Craft CMS plugin to create HTTP requests in your Twig templates to consume JSON, XML or CSV content.
Other
4 stars 1 forks source link

Add fetch event for test mocking #11

Closed markhuot closed 6 months ago

markhuot commented 6 months ago

This adds a hook/event at the beginning of fetchData that would allow external processing to usurp the entire call. I'm using this for test mocking, where we're integrating with a bad API I can't hit from CI. So I match against the request and conditionally return static data instead. My listener looks something like the below (for reference only).

Event::on(
    Service::class,
    Service::EVENT_BEFORE_FETCH_DATA,
    function (FetchEvent $event) {
        $parts = parse_url($event->uri);

        $mocks = [
            ['method' => 'get', 'path' => '#^podcasts$#', 'response' => 'podcasts.json'],
            ['method' => 'get', 'path' => '#^podcasts/([a-z0-9-]+)/seasons$#', 'response' => 'seasons.json'],
            ['method' => 'get', 'path' => '#^podcasts/([a-z0-9-]+)/episodes#', 'response' => 'episode-count.json'],
            ['method' => 'post', 'path' => '#^podcasts/([a-z0-9-]+)/episodes$#', 'response' => 'create-episode.json'],
            ['method' => 'get', 'path' => '#^episodes/([a-z0-9-]+)$#', 'response' => 'episode.json'],
            ['method' => 'post', 'path' => '#^episodes/([a-z0-9-]+)/audio$#', 'response' => 'create-placeholder.json'],
            ['method' => 'put', 'host' => '#^s3.amazonaws.com$#', 'response' => 'upload-audio.json'],
        ];

        foreach ($mocks as $mock) {
            if (! empty($mock['method']) && $mock['method'] !== strtolower($event->method)) {
                continue;
            }
            if (! empty($mock['path']) && preg_match($mock['path'], $parts['path']) == false) {
                continue;
            }
            if (! empty($mock['domain']) && preg_match($mock['host'], $parts['host']) == false) {
                continue;
            }

            $event->isValid = false;
            $event->response = json_decode(file_get_contents(CRAFT_BASE_PATH . '/tests/mocks/simplecast/' . $mock['response']), true, 512, JSON_THROW_ON_ERROR);
            return;
        }

        throw new \RuntimeException('Unexpected remote call made during tests');
    }
);
engram-design commented 6 months ago

Great call, I’m surprised I don’t have this already!

markhuot commented 5 months ago

Woo, thank you!