diff --git a/.editorconfig b/.editorconfig index ae4d693849..8f960391f6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,7 +2,7 @@ root = true [*] -indent_style = spaces +indent_style = space indent_size = 4 end_of_line = lf charset = utf-8 diff --git a/Vagrantfile b/Vagrantfile index fd422311ef..d304fad0fd 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -7,8 +7,12 @@ require 'yaml' VAGRANTFILE_API_VERSION ||= "2" confDir = $confDir ||= File.expand_path("vendor/laravel/homestead", File.dirname(__FILE__)) +# Homestead.yml is the settings file that ships with the repo. Homestead.yaml / +# Homestead.json are gitignored, so a developer can drop one in to override it +# locally; those take precedence. homesteadYamlPath = File.expand_path("Homestead.yaml", File.dirname(__FILE__)) homesteadJsonPath = File.expand_path("Homestead.json", File.dirname(__FILE__)) +homesteadYmlPath = File.expand_path("Homestead.yml", File.dirname(__FILE__)) afterScriptPath = "after.sh" aliasesPath = "aliases" @@ -28,8 +32,10 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| settings = YAML::load(File.read(homesteadYamlPath)) elsif File.exist? homesteadJsonPath then settings = JSON.parse(File.read(homesteadJsonPath)) + elsif File.exist? homesteadYmlPath then + settings = YAML::load(File.read(homesteadYmlPath)) else - abort "Homestead settings file not found in #{confDir}" + abort "Homestead settings file not found in #{File.dirname(__FILE__)}" end # Patch around the pitfalls of the imho dreadful composer update script in Homestead diff --git a/behat.yml.dist b/behat.yml.dist index d56590d1b2..e3e9e16acf 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -14,19 +14,6 @@ default: baseUrl: http://localhost:8000 # proxyUrl: localhost:8888 - Ushahidi\Tests\Integration\Bootstrap\PHPUnitFixtureContext - extensions: - Behat\MinkExtension: - default_session: laravel - base_url: http://localhost:8000 - laravel: ~ - sessions: - default: - goutte: ~ - goutte: - guzzle_parameters: - curl.options: - 3 : 8000 #CURLOPT_PORT=3 - # 10004: localhost:8888 #CURLOPT_PROXY=10004 ci: suites: default: diff --git a/tests/Feature/V3/ExportJobAPI.php b/tests/Feature/V3/ExportJobAPI.php deleted file mode 100644 index 42abc821ce..0000000000 --- a/tests/Feature/V3/ExportJobAPI.php +++ /dev/null @@ -1,81 +0,0 @@ -withoutMiddleware(); - $this->expectsJobs(\Ushahidi\Modules\V3\Jobs\ExportPostsJob::class); - - $this - ->actingAs(new \Ushahidi\Authzn\GenericUser(['id' => 2])) - ->json('POST', '/api/v3/exports/jobs', [ - 'fields' => 'test', - 'filters' => [ - 'status' => ['published', 'draft'], - ], - 'entity_type' => 'post', - 'send_to_browser' => true, - 'send_to_hdx' => false, - 'hxl_heading_row' => ['something'], - ]); - - $this->seeStatusCode('200') - ->seeJson([ - 'fields' => ['test'], - 'filters' => [ - 'status' => ['published', 'draft'], - ], - 'entity_type' => 'post', - 'send_to_browser' => true, - 'send_to_hdx' => false, - 'hxl_heading_row' => null, - ]); - } - - /** - * Create a job - */ - public function testCreateJobWithRealDispatch() - { - $this->withoutMiddleware(); - - $this - ->actingAs(new \Ushahidi\Modules\Auth\GenericUser(['id' => 2])) - ->json('POST', '/api/v3/exports/jobs', [ - 'fields' => 'test', - 'filters' => [ - 'status' => ['published', 'draft'], - ], - 'entity_type' => 'post', - 'send_to_browser' => true, - 'send_to_hdx' => false, - 'hxl_heading_row' => ['something'], - ]); - - $this->seeStatusCode('200') - ->seeJson([ - 'fields' => ['test'], - 'filters' => [ - 'status' => ['published', 'draft'], - ], - 'entity_type' => 'post', - 'send_to_browser' => true, - 'send_to_hdx' => false, - 'hxl_heading_row' => null, - ]); - } -} diff --git a/tests/Feature/V3/ExportJobAPITest.php b/tests/Feature/V3/ExportJobAPITest.php new file mode 100644 index 0000000000..218fbb806f --- /dev/null +++ b/tests/Feature/V3/ExportJobAPITest.php @@ -0,0 +1,100 @@ + 'test', + 'filters' => [ + 'status' => ['published', 'draft'], + ], + 'entity_type' => 'post', + 'send_to_browser' => true, + 'send_to_hdx' => false, + 'hxl_heading_row' => ['something'], + ]; + + private const EXPECTED = [ + 'fields' => ['test'], + 'filters' => [ + 'status' => ['published', 'draft'], + ], + 'entity_type' => 'post', + 'send_to_browser' => true, + 'send_to_hdx' => false, + 'hxl_heading_row' => null, + ]; + + /** + * Creating an export job requires admin rights. The test owns its admin + * user rather than relying on a fixture: the behat dataset is not loaded + * for phpunit runs, and it rewrites the users table when it is. + */ + protected $adminId; + + public function setUp(): void + { + parent::setUp(); + + $faker = Faker\Factory::create(); + + $this->adminId = service('repository.user')->create(new User([ + 'email' => $faker->unique()->safeEmail, + 'realname' => 'Export Admin', + 'role' => 'admin', + ])); + } + + public function tearDown(): void + { + service('repository.user')->delete(new User(['id' => $this->adminId])); + + parent::tearDown(); + } + + private function postJob() + { + return $this->actingAs(new GenericUser(['id' => $this->adminId])) + ->json('POST', '/api/v3/exports/jobs', self::REQUEST); + } + + /** + * Create a job, asserting the export is queued rather than run inline. + */ + public function testCreateJob() + { + Bus::fake(); + + $this->withoutMiddleware(); + + $this->postJob() + ->assertStatus(200) + ->assertJson(self::EXPECTED); + + Bus::assertDispatched(ExportPostsJob::class); + } + + /** + * Create a job and let the export actually dispatch. + */ + public function testCreateJobWithRealDispatch() + { + $this->withoutMiddleware(); + + $this->postJob() + ->assertStatus(200) + ->assertJson(self::EXPECTED); + } +} diff --git a/tests/Feature/V3/WebhooksPostsUpdateAPI.php b/tests/Feature/V3/WebhooksPostsUpdateAPITest.php similarity index 59% rename from tests/Feature/V3/WebhooksPostsUpdateAPI.php rename to tests/Feature/V3/WebhooksPostsUpdateAPITest.php index d75bdead44..c7e8728706 100644 --- a/tests/Feature/V3/WebhooksPostsUpdateAPI.php +++ b/tests/Feature/V3/WebhooksPostsUpdateAPITest.php @@ -1,26 +1,21 @@ delete(new Post(['id' => $this->postId])); @@ -46,31 +41,27 @@ protected function makeSig($sharedSecret, $url, $payload) return base64_encode(hash_hmac('sha256', $data, $sharedSecret, true)); } - /** - * Get count - */ public function testUpdate() { $this->withoutMiddleware(); + $this->json('PUT', '/api/v3/webhooks/posts/'.$this->postId, [ 'title' => 'Updated', 'content' => 'Also updated', - ]); - - $this->seeStatusCode('200') - ->seeJson([ + ]) + ->assertStatus(200) + ->assertJson([ 'title' => 'Updated', 'content' => 'Also updated', ]); } /** - * Update a job + * Middleware is left enabled here: the point of the test is that a request + * carrying a valid X-Ushahidi-Signature is accepted. */ public function testUpdateWithSignature() { - // Re-enable middleware - $this->app->instance('middleware.disable', false); // Set the shared secret $originalSecret = getenv('PLATFORM_SHARED_SECRET'); putenv('PLATFORM_SHARED_SECRET=asharedsecret'); @@ -80,32 +71,23 @@ public function testUpdateWithSignature() $apiKeyId = $apiKeys->create(new ApiKey([])); $apiKey = $apiKeys->get($apiKeyId); + $url = '/api/v3/webhooks/posts/'.$this->postId.'?api_key='.$apiKey->api_key; + + $payload = [ + 'title' => 'Updated w/sig', + 'content' => 'Also updated', + ]; + // Make a signature $sig = $this->makeSig( 'asharedsecret', - $this->prepareUrlForRequest( - '/api/v3/webhooks/posts/'.$this->postId.'?api_key='.$apiKey->api_key - ), - json_encode([ - 'title' => 'Updated w/sig', - 'content' => 'Also updated', - ]) + $this->prepareUrlForRequest($url), + json_encode($payload) ); - $this->json( - 'PUT', - '/api/v3/webhooks/posts/'.$this->postId.'?api_key='.$apiKey->api_key, - [ - 'title' => 'Updated w/sig', - 'content' => 'Also updated', - ], - [ - 'X-Ushahidi-Signature' => $sig, - ] - ); - - $this->seeStatusCode('200') - ->seeJsonStructure([ + $this->json('PUT', $url, $payload, ['X-Ushahidi-Signature' => $sig]) + ->assertStatus(200) + ->assertJsonStructure([ 'id', 'user_id', 'type', @@ -116,10 +98,7 @@ public function testUpdateWithSignature() 'created', 'updated', ]) - ->seeJson([ - 'title' => 'Updated w/sig', - 'content' => 'Also updated', - ]); + ->assertJson($payload); // Clean up $apiKeys->delete($apiKey);