diff --git a/CHANGELOG.md b/CHANGELOG.md index 1945e4599..b81797e0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +* **Build 297** (2015-09-16) + - Fixed a bug in deferred binding that allowed repeat bindings and ignored add/delete pairs. + * **Build 293** (2015-09-07) - Corrected a flaw in the Behavior/Extension logic that previously made protected methods and properties accessible as if they were public. diff --git a/tests/unit/plugins/database/BelongsToModelTest.php b/tests/unit/plugins/database/BelongsToModelTest.php index 06886e7c5..fb7d95ed8 100644 --- a/tests/unit/plugins/database/BelongsToModelTest.php +++ b/tests/unit/plugins/database/BelongsToModelTest.php @@ -15,7 +15,7 @@ class BelongsToModelTest extends PluginTestCase $this->runPluginRefreshCommand('Database.Tester'); } - public function testSetRelationValueBelongsTo() + public function testSetRelationValue() { Model::unguard(); $post = Post::create(['title' => "First post", 'description' => "Yay!!"]); @@ -39,11 +39,52 @@ class BelongsToModelTest extends PluginTestCase $this->assertNull($post->author_id); $this->assertNull($post->author); - // Deferred + // Deferred in memory $post->author = $author3; $this->assertEquals('Charlie', $post->author->name); $this->assertNull($post->author_id); $author3->save(); $this->assertEquals($author3->id, $post->author_id); } + + public function testDeferredBinding() + { + $sessionKey = uniqid('session_key', true); + + Model::unguard(); + $post = Post::make(['title' => "First post"]); + $author = Author::create(['name' => 'Stevie']); + Model::reguard(); + + // Deferred add + $post->author()->add($author, $sessionKey); + $this->assertNull($post->author_id); + $this->assertNull($post->author); + + $this->assertEquals(0, $post->author()->count()); + $this->assertEquals(1, $post->author()->withDeferred($sessionKey)->count()); + + // Commit deferred + $post->save(null, $sessionKey); + $this->assertEquals(1, $post->author()->count()); + $this->assertEquals($author->id, $post->author_id); + $this->assertEquals('Stevie', $post->author->name); + + // New session + $sessionKey = uniqid('session_key', true); + + // Deferred remove + $post->author()->remove($author, $sessionKey); + $this->assertEquals(1, $post->author()->count()); + $this->assertEquals(0, $post->author()->withDeferred($sessionKey)->count()); + $this->assertEquals($author->id, $post->author_id); + $this->assertEquals('Stevie', $post->author->name); + + // Commit deferred + $post->save(null, $sessionKey); + $this->assertEquals(0, $post->author()->count()); + $this->assertNull($post->author_id); + $this->assertNull($post->author); + } + } \ No newline at end of file diff --git a/tests/unit/plugins/database/DeferredBindingTest.php b/tests/unit/plugins/database/DeferredBindingTest.php new file mode 100644 index 000000000..b79acbd67 --- /dev/null +++ b/tests/unit/plugins/database/DeferredBindingTest.php @@ -0,0 +1,109 @@ +runPluginRefreshCommand('Database.Tester'); + } + + public function testNegatedBinding() + { + $sessionKey = uniqid('session_key', true); + DeferredBinding::truncate(); + + Model::unguard(); + $author = Author::make(['name' => 'Stevie']); + $post = Post::create(['title' => "First post"]); + $post2 = Post::create(['title' => "Second post"]); + Model::reguard(); + + $author->posts()->add($post, $sessionKey); + $this->assertEquals(1, DeferredBinding::count()); + + // Skip repeat bindings + $author->posts()->add($post, $sessionKey); + $this->assertEquals(1, DeferredBinding::count()); + + // Remove add-delete pairs + $author->posts()->remove($post, $sessionKey); + $this->assertEquals(0, DeferredBinding::count()); + + // Multi ball + $sessionKey = uniqid('session_key', true); + $author->posts()->add($post, $sessionKey); + $author->posts()->add($post, $sessionKey); + $author->posts()->add($post, $sessionKey); + $author->posts()->add($post, $sessionKey); + $author->posts()->add($post2, $sessionKey); + $author->posts()->add($post2, $sessionKey); + $author->posts()->add($post2, $sessionKey); + $author->posts()->add($post2, $sessionKey); + $author->posts()->add($post2, $sessionKey); + $this->assertEquals(2, DeferredBinding::count()); + + // Clean up add-delete pairs + $author->posts()->remove($post, $sessionKey); + $author->posts()->remove($post2, $sessionKey); + $this->assertEquals(0, DeferredBinding::count()); + + // Double negative + $author->posts()->remove($post, $sessionKey); + $author->posts()->remove($post2, $sessionKey); + $this->assertEquals(2, DeferredBinding::count()); + + // Skip repeat bindings + $author->posts()->remove($post, $sessionKey); + $author->posts()->remove($post2, $sessionKey); + $this->assertEquals(2, DeferredBinding::count()); + + // Clean up add-delete pairs again + $author->posts()->add($post, $sessionKey); + $author->posts()->add($post2, $sessionKey); + $this->assertEquals(0, DeferredBinding::count()); + } + + public function testCancelBinding() + { + $sessionKey = uniqid('session_key', true); + DeferredBinding::truncate(); + + Model::unguard(); + $author = Author::make(['name' => 'Stevie']); + $post = Post::create(['title' => "First post"]); + Model::reguard(); + + $author->posts()->add($post, $sessionKey); + $this->assertEquals(1, DeferredBinding::count()); + + $author->cancelDeferred($sessionKey); + $this->assertEquals(0, DeferredBinding::count()); + } + + public function testCommitBinding() + { + $sessionKey = uniqid('session_key', true); + DeferredBinding::truncate(); + + Model::unguard(); + $author = Author::make(['name' => 'Stevie']); + $post = Post::create(['title' => "First post"]); + Model::reguard(); + + $author->posts()->add($post, $sessionKey); + $this->assertEquals(1, DeferredBinding::count()); + + $author->commitDeferred($sessionKey); + $this->assertEquals(0, DeferredBinding::count()); + } + +} \ No newline at end of file