Repository: def-studio/telegraph (php)

Issue:
Delete Webhook
The documentation makes reference to delete a webhook, but the functionality for this isn’t available.

Pull request:
implements unregisterWebhook call
this PR will add the `unregisterWebhook` method

closes #79 

Patch:
diff --git a/docs/content/en/features/telegram-api-calls.md b/docs/content/en/features/telegram-api-calls.md
index 2f39d0e4..29296254 100644
--- a/docs/content/en/features/telegram-api-calls.md
+++ b/docs/content/en/features/telegram-api-calls.md
@@ -41,7 +41,7 @@ retrieves the bot updates from Telegram APIs
 Telegram::bot($telegraphBot)->botUpdates()->send();
 ```
 
-<alert type="alert">Manual updates polling is not available if a webhook is set up for the bot. Webhook should be remove first using its [deleteWebhook](webhooks/deleting-webhooks) methods</alert>
+<alert type="alert">Manual updates polling is not available if a webhook is set up for the bot. Webhook should be remove first using its [unregisterWebhook](webhooks/deleting-webhooks) method</alert>
 
 ## chatAction
 
@@ -182,3 +182,11 @@ resets Telegram Bot registered commands
 ```php
 Telegram::unregisterBotCommands()->send();
 ```
+
+## unregisterWebhook
+
+unregister a webhook for the active bot
+
+```php
+Telegram::registerWebhook()->send();
+```
diff --git a/docs/content/en/models/telegraph-bot.md b/docs/content/en/models/telegraph-bot.md
index fe59b16d..1c7b7709 100644
--- a/docs/content/en/models/telegraph-bot.md
+++ b/docs/content/en/models/telegraph-bot.md
@@ -101,6 +101,16 @@ register a webhook url
 $telegraphBot->registerWebhook()->send();
 ```
 
+### `unregisterWebhook()`
+
+unregister a webhook url
+
+```php
+/** @var \DefStudio\Telegraph\Models\TelegraphBot $telegraphBot */
+
+$telegraphBot->unregisterWebhook()->send();
+```
+
 ### `getWebhookDebugInfo()`
 
 retrieves webhook debug data
diff --git a/docs/content/en/webhooks/callback-data.md b/docs/content/en/webhooks/callback-data.md
index b9d0727e..774a607a 100644
--- a/docs/content/en/webhooks/callback-data.md
+++ b/docs/content/en/webhooks/callback-data.md
@@ -4,7 +4,7 @@ menuTitle: 'Callback Data'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 62
+position: 64
 ---
 
 Callback query data must be defined with the following structure:
diff --git a/docs/content/en/webhooks/callback-reply.md b/docs/content/en/webhooks/callback-reply.md
index d6f94c90..8bfe6bb0 100644
--- a/docs/content/en/webhooks/callback-reply.md
+++ b/docs/content/en/webhooks/callback-reply.md
@@ -4,7 +4,7 @@ menuTitle: 'Callback Reply'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 63
+position: 65
 ---
 
 
diff --git a/docs/content/en/webhooks/deleting-webhooks.md b/docs/content/en/webhooks/deleting-webhooks.md
index 6c195303..8fdb876c 100644
--- a/docs/content/en/webhooks/deleting-webhooks.md
+++ b/docs/content/en/webhooks/deleting-webhooks.md
@@ -1,16 +1,44 @@
 ---
-title: 'Deleting Webhooks'
+title: 'Regitering Webhooks'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 66
+position: 62
 ---
 
-
-[//]: # (todo)
+A webhook can be unergistered from a telegraph bot. This can be accomplished both programmatically and through an artisan command
 
 ## artisan command
 
+You can unregister a webhook calling the `telegraph:unset-webhook` artisan command:
+
+```shell
+php artisan telegraph:unset-webhook
+```
+
 ## programmatically
 
-<alert type="alert">Manual updates polling is not available if a webhook is set up for the bot. Webhook should be remove first using its [deleteWebhook](webhooks/deleting-webhooks) methods</alert>
+if you are implementing a custom bot management logic, you can unregister a webhok using the `TelegraphBot` model:
+
+```php
+/** @var DefStudio\Telegraph\Models\TelegraphBot $telegraphBot */
+
+$telegraphBot->unregisterWebhook()->send();
+```
+
+
+### Pending updates
+
+It may happen that there are pending message updates when deleting a webhook. By default they are kept in order to retrieve them through a manual polling. To drop these updates, use the `--drop-pending-updates` artisan command option
+
+```shell
+php artisan telegraph:unset-webhook --drop-pending-updates
+```
+
+or using a parameter inside the method call:
+
+```php
+$dropPendingUpdates = true;
+
+$telegraphBot->unregisterWebhook($dropPendingUpdates)->send();
+```
diff --git a/docs/content/en/webhooks/dto.md b/docs/content/en/webhooks/dto.md
index 063dc7ec..4b9fed2a 100644
--- a/docs/content/en/webhooks/dto.md
+++ b/docs/content/en/webhooks/dto.md
@@ -3,7 +3,7 @@ title: 'Incoming Data'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 67
+position: 68
 ---
 
 Data obtained from manual polling or webhooks is available through a set of DTO:
diff --git a/docs/content/en/webhooks/keyboard-interaction.md b/docs/content/en/webhooks/keyboard-interaction.md
index a608110e..b27773eb 100644
--- a/docs/content/en/webhooks/keyboard-interaction.md
+++ b/docs/content/en/webhooks/keyboard-interaction.md
@@ -4,7 +4,7 @@ menuTitle: 'Keyboard Interaction'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 64
+position: 66
 ---
 
 
diff --git a/docs/content/en/webhooks/manual-polling.md b/docs/content/en/webhooks/manual-polling.md
index 6306c2a2..a568968e 100644
--- a/docs/content/en/webhooks/manual-polling.md
+++ b/docs/content/en/webhooks/manual-polling.md
@@ -4,12 +4,12 @@ menuTitle: 'Manual Polling'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 66
+position: 67
 ---
 
 As an aternative to set up a webhook, a bot updates can be fetched by periodically polling Telegram APIs
 
-<alert type="alert">Manual updates polling is not available if a webhook is set up for the bot. Webhook should be remove first using its [deleteWebhook](webhooks/deleting-webhooks) methods</alert>
+<alert type="alert">Manual updates polling is not available if a webhook is set up for the bot. Webhook should be remove first using its [unregisterWebhook](webhooks/deleting-webhooks) method</alert>
 
 in order to get the updates, an `->updates()` method is available in the [TelegraphBot](models/telegraph-bot) model:
 
diff --git a/docs/content/en/webhooks/registering-webhooks.md b/docs/content/en/webhooks/registering-webhooks.md
new file mode 100644
index 00000000..aa24d1b8
--- /dev/null
+++ b/docs/content/en/webhooks/registering-webhooks.md
@@ -0,0 +1,29 @@
+---
+title: 'Register Webhooks'
+description: ''
+category: 'Webhooks'
+fullscreen: false 
+position: 61
+---
+
+In order to receive Telegram updates through a webhook, it has to be registered to a specific bot. This can be accomplished both programmatically and through an artisan command
+
+## artisan command
+
+You can register a webhook calling the `telegraph:set-webhook` artisan command:
+
+```shell
+php artisan telegraph:set-webhook
+```
+
+## programmatically
+
+if you are implementing a custom bot management logic, you can register a webhok using the `TelegraphBot` model:
+
+```php
+/** @var DefStudio\Telegraph\Models\TelegraphBot $telegraphBot */
+
+$telegraphBot->registerWebhook()->send();
+```
+
+<alert type="alert">Manual updates polling is not available if a webhook is set up for the bot. Webhook should be remove first using its [unregisterWebhook](webhooks/deleting-webhooks) method</alert>
diff --git a/docs/content/en/webhooks/webhook-request-types.md b/docs/content/en/webhooks/webhook-request-types.md
index 6c507006..b5d472c5 100644
--- a/docs/content/en/webhooks/webhook-request-types.md
+++ b/docs/content/en/webhooks/webhook-request-types.md
@@ -4,7 +4,7 @@ menuTitle: 'Request Types'
 description: ''
 category: 'Webhooks'
 fullscreen: false 
-position: 61
+position: 64
 ---
 
 
diff --git a/src/Client/TelegraphResponse.php b/src/Client/TelegraphResponse.php
index 00a4f67f..9c0cc2c2 100644
--- a/src/Client/TelegraphResponse.php
+++ b/src/Client/TelegraphResponse.php
@@ -27,7 +27,22 @@ class TelegraphResponse extends Response
             return null;
         }
 
-        /* @phpstan-ignore-next-line   */
+        /* @phpstan-ignore-next-line */
         return (int) $this->json('result.message_id');
     }
+
+    public function dump(): static
+    {
+        dump($this->json());
+
+        return $this;
+    }
+
+    /**
+     * @return never-returns
+     */
+    public function dd(): void
+    {
+        dd($this->json());
+    }
 }
diff --git a/src/Commands/UnsetTelegramWebhookCommand.php b/src/Commands/UnsetTelegramWebhookCommand.php
new file mode 100644
index 00000000..394ec788
--- /dev/null
+++ b/src/Commands/UnsetTelegramWebhookCommand.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace DefStudio\Telegraph\Commands;
+
+use DefStudio\Telegraph\Models\TelegraphBot;
+use Illuminate\Console\Command;
+
+class UnsetTelegramWebhookCommand extends Command
+{
+    public $signature = 'telegraph:unset-webhook
+                            {bot? : the ID of the bot (if the system contain a single bot, it can be left empty)}
+                            {--drop-pending-updates: if set, upon webhook deletion, all pending updates will be discarded}';
+
+    public $description = 'Unregister the webhook in telegram bot configuration';
+
+    public function handle(): int
+    {
+        /** @var int|null $bot_id */
+        $bot_id = $this->argument('bot');
+
+        /** @var TelegraphBot|null $bot */
+        $bot = rescue(fn () => TelegraphBot::fromId($bot_id), report: false);
+
+        if (empty($bot)) {
+            $this->error("Please specify a Bot ID");
+
+            return self::FAILURE;
+        }
+
+        $telegraph = $bot->unregisterWebhook($this->hasOption('drop-pending-updates'));
+
+        $this->info("Sending webhook unset request to: {$telegraph->getApiUrl()}");
+
+        $reponse = $telegraph->send();
+
+        $ok = (bool)$reponse->json('ok');
+
+        if (!$ok) {
+            $this->error("Failed to unregister webhook");
+            $this->error($reponse->body());
+
+            return self::FAILURE;
+        }
+
+        $this->info('Webhook deleted');
+
+        return self::SUCCESS;
+    }
+}
diff --git a/src/Concerns/InteractsWithWebhooks.php b/src/Concerns/InteractsWithWebhooks.php
index a9a8f472..7355392f 100644
--- a/src/Concerns/InteractsWithWebhooks.php
+++ b/src/Concerns/InteractsWithWebhooks.php
@@ -4,6 +4,7 @@
 
 namespace DefStudio\Telegraph\Concerns;
 
+use DefStudio\Telegraph\Exceptions\TelegramWebhookException;
 use DefStudio\Telegraph\Telegraph;
 
 /**
@@ -15,9 +16,27 @@ trait InteractsWithWebhooks
     {
         $telegraph = clone $this;
 
+        $url = route('telegraph.webhook', $telegraph->getBot());
+
+        if (!str_starts_with($url, 'https://')) {
+            throw TelegramWebhookException::invalidScheme();
+        }
+
         $telegraph->endpoint = self::ENDPOINT_SET_WEBHOOK;
         $telegraph->data = [
-            'url' => route('telegraph.webhook', $telegraph->getBot()),
+            'url' => $url,
+        ];
+
+        return $telegraph;
+    }
+
+    public function unregisterWebhook(bool $dropPendingUpdates = false): Telegraph
+    {
+        $telegraph = clone $this;
+
+        $telegraph->endpoint = self::ENDPOINT_UNSET_WEBHOOK;
+        $telegraph->data = [
+            'drop_pending_updates' => $dropPendingUpdates,
         ];
 
         return $telegraph;
diff --git a/src/Exceptions/TelegramWebhookException.php b/src/Exceptions/TelegramWebhookException.php
index b7ee0852..02342c0a 100644
--- a/src/Exceptions/TelegramWebhookException.php
+++ b/src/Exceptions/TelegramWebhookException.php
@@ -18,4 +18,9 @@ class TelegramWebhookException extends \Exception
     {
         return new self("Invalid data: $description");
     }
+
+    public static function invalidScheme(): TelegramWebhookException
+    {
+        return new self("You application must have a secure (https) url in order to accept webhook calls");
+    }
 }
diff --git a/src/Facades/Telegraph.php b/src/Facades/Telegraph.php
index 95ed0df0..0aa08f84 100644
--- a/src/Facades/Telegraph.php
+++ b/src/Facades/Telegraph.php
@@ -18,6 +18,7 @@ use Illuminate\Support\Facades\Facade;
  * @method static \DefStudio\Telegraph\Telegraph  reply(int $messageId)
  * @method static \DefStudio\Telegraph\Telegraph  markdown(string $message)
  * @method static \DefStudio\Telegraph\Telegraph  registerWebhook()
+ * @method static \DefStudio\Telegraph\Telegraph  unregisterWebhook(bool $dropPendingUpdates = false)
  * @method static \DefStudio\Telegraph\Telegraph  registerBotCommands(array $commands)
  * @method static \DefStudio\Telegraph\Telegraph  unregisterBotCommands()
  * @method static \DefStudio\Telegraph\Telegraph  getWebhookDebugInfo()
@@ -37,6 +38,7 @@ use Illuminate\Support\Facades\Facade;
  * @method static void  assertSent(string $message, bool $exact = true)
  * @method static void  assertNothingSent()
  * @method static void  assertRegisteredWebhook()
+ * @method static void  assertUnregisteredWebhook()
  * @method static void  assertRequestedWebhookDebugInfo()
  * @method static void  assertRepliedWebhook(string $message)
  * @method static void  assertStoredFile(string $fileId)
diff --git a/src/Models/TelegraphBot.php b/src/Models/TelegraphBot.php
index 96f6f003..455fb4fd 100644
--- a/src/Models/TelegraphBot.php
+++ b/src/Models/TelegraphBot.php
@@ -90,6 +90,11 @@ class TelegraphBot extends Model
         return TelegraphFacade::bot($this)->registerWebhook();
     }
 
+    public function unregisterWebhook(bool $dropPendingUpdates = false): Telegraph
+    {
+        return TelegraphFacade::bot($this)->unregisterWebhook($dropPendingUpdates);
+    }
+
     public function getWebhookDebugInfo(): Telegraph
     {
         return TelegraphFacade::bot($this)->getWebhookDebugInfo();
diff --git a/src/Telegraph.php b/src/Telegraph.php
index c4155ced..92aeb8a6 100755
--- a/src/Telegraph.php
+++ b/src/Telegraph.php
@@ -50,6 +50,7 @@ class Telegraph
     public const ENDPOINT_REGISTER_BOT_COMMANDS = 'setMyCommands';
     public const ENDPOINT_UNREGISTER_BOT_COMMANDS = 'deleteMyCommands';
     public const ENDPOINT_SET_WEBHOOK = 'setWebhook';
+    public const ENDPOINT_UNSET_WEBHOOK = 'deleteWebhook';
     public const ENDPOINT_GET_WEBHOOK_DEBUG_INFO = 'getWebhookInfo';
     public const ENDPOINT_ANSWER_WEBHOOK = 'answerCallbackQuery';
     public const ENDPOINT_REPLACE_KEYBOARD = 'editMessageReplyMarkup';
@@ -85,4 +86,19 @@ class Telegraph
     {
         return $this->dispatchRequestToTelegram($queue);
     }
+
+    /**
+     * @return never-returns
+     */
+    public function dd(): void
+    {
+        dd($this->toArray());
+    }
+
+    public function dump(): Telegraph
+    {
+        dump($this->toArray());
+
+        return $this;
+    }
 }
diff --git a/src/TelegraphServiceProvider.php b/src/TelegraphServiceProvider.php
index 61787f10..8ac04b53 100644
--- a/src/TelegraphServiceProvider.php
+++ b/src/TelegraphServiceProvider.php
@@ -6,6 +6,7 @@ use DefStudio\Telegraph\Commands\CreateNewBotCommand;
 use DefStudio\Telegraph\Commands\CreateNewChatCommand;
 use DefStudio\Telegraph\Commands\GetTelegramWebhookDebugInfoCommand;
 use DefStudio\Telegraph\Commands\SetTelegramWebhookCommand;
+use DefStudio\Telegraph\Commands\UnsetTelegramWebhookCommand;
 use Spatie\LaravelPackageTools\Package;
 use Spatie\LaravelPackageTools\PackageServiceProvider;
 
@@ -22,6 +23,7 @@ class TelegraphServiceProvider extends PackageServiceProvider
             ->hasCommand(CreateNewBotCommand::class)
             ->hasCommand(CreateNewChatCommand::class)
             ->hasCommand(SetTelegramWebhookCommand::class)
+            ->hasCommand(UnsetTelegramWebhookCommand::class)
             ->hasCommand(GetTelegramWebhookDebugInfoCommand::class);
 
         $this->app->bind('telegraph', fn () => new Telegraph());
diff --git a/x-ray.yml b/x-ray.yml
index 7efcecd9..b7e96a25 100644
--- a/x-ray.yml
+++ b/x-ray.yml
@@ -14,3 +14,5 @@ paths:
     - 'docs/*'
     - 'vendor/*'
     - 'src/Support/Testing/Fakes/TelegraphFake.php'
+    - 'src/Telegraph.php'
+    - 'src/Client/TelegraphResponse.php'


Test patch:
diff --git a/src/Support/Testing/Fakes/TelegraphFake.php b/src/Support/Testing/Fakes/TelegraphFake.php
index ed699347..6d04a0f3 100644
--- a/src/Support/Testing/Fakes/TelegraphFake.php
+++ b/src/Support/Testing/Fakes/TelegraphFake.php
@@ -357,6 +357,11 @@ class TelegraphFake extends Telegraph
         $this->assertSentData(Telegraph::ENDPOINT_SET_WEBHOOK);
     }
 
+    public function assertUnregisteredWebhook(): void
+    {
+        $this->assertSentData(Telegraph::ENDPOINT_UNSET_WEBHOOK);
+    }
+
     public function assertRequestedWebhookDebugInfo(): void
     {
         $this->assertSentData(Telegraph::ENDPOINT_GET_WEBHOOK_DEBUG_INFO);
diff --git a/tests/Feature/Commands/CreateNewBotCommandTest.php b/tests/Feature/Commands/CreateNewBotCommandTest.php
index bb7b2c5d..7236ec98 100644
--- a/tests/Feature/Commands/CreateNewBotCommandTest.php
+++ b/tests/Feature/Commands/CreateNewBotCommandTest.php
@@ -95,6 +95,8 @@ it('keeps asking for the chat name until pressed x', function () {
 });
 
 it('can register the new bot webhook', function () {
+    withfakeUrl();
+
     Facade::fake([
         Telegraph::ENDPOINT_SET_WEBHOOK => [
             'ok' => true,
diff --git a/tests/Feature/Commands/SetTelegramWebhookCommandTest.php b/tests/Feature/Commands/SetTelegramWebhookCommandTest.php
index 4f1a03d8..50243a69 100644
--- a/tests/Feature/Commands/SetTelegramWebhookCommandTest.php
+++ b/tests/Feature/Commands/SetTelegramWebhookCommandTest.php
@@ -9,6 +9,7 @@ use Symfony\Component\Console\Command\Command;
 uses(LazilyRefreshDatabase::class);
 
 test('can set telegram webhook address if there is only one', function () {
+    withfakeUrl();
     bot();
 
     Telegraph::fake();
@@ -28,7 +29,8 @@ test('it requires bot id if there are more than one', function () {
         ->assertExitCode(Command::FAILURE);
 });
 
-test('can set tel0egram webhook address for a bot if given its ID', function () {
+test('can set telegram webhook address for a bot if given its ID', function () {
+    withfakeUrl();
     $bot = bots(2)->first();
 
     Telegraph::fake();
@@ -40,6 +42,7 @@ test('can set tel0egram webhook address for a bot if given its ID', function ()
 });
 
 test('it dumps error when telegram request is unsuccessful', function () {
+    withfakeUrl();
     $bot = bots(2)->first();
 
     Telegraph::fake([
diff --git a/tests/Feature/Commands/UnsetTelegramWebhookCommandTest.php b/tests/Feature/Commands/UnsetTelegramWebhookCommandTest.php
new file mode 100644
index 00000000..d6b0781f
--- /dev/null
+++ b/tests/Feature/Commands/UnsetTelegramWebhookCommandTest.php
@@ -0,0 +1,57 @@
+<?php
+
+
+use DefStudio\Telegraph\Facades\Telegraph;
+use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
+use function Pest\Laravel\artisan;
+use Symfony\Component\Console\Command\Command;
+
+uses(LazilyRefreshDatabase::class);
+
+test('can set telegram webhook address if there is only one', function () {
+    bot();
+
+    Telegraph::fake();
+
+    /** @phpstan-ignore-next-line */
+    artisan('telegraph:unset-webhook')
+        ->expectsOutput("Webhook deleted")
+        ->assertExitCode(Command::SUCCESS);
+});
+
+test('it requires bot id if there are more than one', function () {
+    bots(2);
+
+    /** @phpstan-ignore-next-line */
+    artisan('telegraph:unset-webhook')
+        ->expectsOutput("Please specify a Bot ID")
+        ->assertExitCode(Command::FAILURE);
+});
+
+test('can set telegram webhook address for a bot if given its ID', function () {
+    $bot = bots(2)->first();
+
+    Telegraph::fake();
+
+    /** @phpstan-ignore-next-line */
+    artisan("telegraph:unset-webhook $bot->id")
+        ->expectsOutput("Webhook deleted")
+        ->assertExitCode(Command::SUCCESS);
+});
+
+test('it dumps error when telegram request is unsuccessful', function () {
+    $bot = bots(2)->first();
+
+    Telegraph::fake([
+        \DefStudio\Telegraph\Telegraph::ENDPOINT_UNSET_WEBHOOK => [
+            'ok' => false,
+            'foo' => 'bar',
+        ],
+    ]);
+
+    /** @phpstan-ignore-next-line */
+    artisan("telegraph:unset-webhook $bot->id")
+        ->expectsOutput("Failed to unregister webhook")
+        ->expectsOutput('{"ok":false,"foo":"bar"}')
+        ->assertExitCode(Command::FAILURE);
+});
diff --git a/tests/Pest.php b/tests/Pest.php
index ae0024d4..bb0df1ad 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -11,12 +11,21 @@ use DefStudio\Telegraph\Tests\Support\TestWebhookHandler;
 use DefStudio\Telegraph\Tests\TestCase;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\URL;
 
 uses(TestCase::class)->in("Feature");
 uses(TestCase::class)->in("Unit");
 uses(TestCase::class)->in("Regression");
 uses(TestCase::class)->group('sandbox')->in("Sandbox");
 
+function withfakeUrl(): string
+{
+    $url = 'https://testbot.defstudio.dev';
+    URL::forceScheme('https');
+    URL::forceRootUrl($url);
+
+    return $url;
+}
 
 /**
  * @return Collection<TelegraphBot>
diff --git a/tests/Unit/Concerns/HasBotsAndChatsTest.php b/tests/Unit/Concerns/HasBotsAndChatsTest.php
index 1b258690..f60acb91 100644
--- a/tests/Unit/Concerns/HasBotsAndChatsTest.php
+++ b/tests/Unit/Concerns/HasBotsAndChatsTest.php
@@ -10,7 +10,9 @@ use DefStudio\Telegraph\Facades\Telegraph;
 use function Spatie\Snapshots\assertMatchesSnapshot;
 
 it('can customize the destination bot', function () {
+    withfakeUrl();
     $bot = make_bot();
+
     $telegraph = Telegraph::bot($bot)
         ->registerWebhook();
 
diff --git a/tests/Unit/Concerns/InteractsWithWebhooksTest.php b/tests/Unit/Concerns/InteractsWithWebhooksTest.php
index 2675519d..277b9344 100644
--- a/tests/Unit/Concerns/InteractsWithWebhooksTest.php
+++ b/tests/Unit/Concerns/InteractsWithWebhooksTest.php
@@ -1,12 +1,30 @@
 <?php
 
+/** @noinspection PhpUnhandledExceptionInspection */
+
+use DefStudio\Telegraph\Exceptions\TelegramWebhookException;
 use DefStudio\Telegraph\Telegraph;
 
 it('can register a webhook', function () {
+    withfakeUrl();
     expect(fn (Telegraph $telegraph) => $telegraph->bot(make_bot())->registerWebhook())
         ->toMatchTelegramSnapshot();
 });
 
+it('requires an https url to register a webhook', function () {
+    \DefStudio\Telegraph\Facades\Telegraph::bot(make_bot())->registerWebhook();
+})->throws(TelegramWebhookException::class, 'You application must have a secure (https) url in order to accept webhook calls');
+
+it('can unregister a webhook', function () {
+    expect(fn (Telegraph $telegraph) => $telegraph->bot(make_bot())->unregisterWebhook())
+        ->toMatchTelegramSnapshot();
+});
+
+it('can unregister a webhook dropping all pending updates', function () {
+    expect(fn (Telegraph $telegraph) => $telegraph->bot(make_bot())->unregisterWebhook(true))
+        ->toMatchTelegramSnapshot();
+});
+
 it('can get webhook debug info', function () {
     expect(fn (Telegraph $telegraph) => $telegraph->bot(make_bot())->getWebhookDebugInfo())
         ->toMatchTelegramSnapshot();
diff --git a/tests/Unit/Models/TelegraphBotTest.php b/tests/Unit/Models/TelegraphBotTest.php
index e53949c8..7dfe764f 100644
--- a/tests/Unit/Models/TelegraphBotTest.php
+++ b/tests/Unit/Models/TelegraphBotTest.php
@@ -21,6 +21,8 @@ it('can retrieve its url', function () {
 });
 
 it('can register its webhook', function () {
+    withfakeUrl();
+
     Telegraph::fake();
     $bot = make_bot();
 
@@ -29,6 +31,15 @@ it('can register its webhook', function () {
     Telegraph::assertRegisteredWebhook();
 });
 
+it('can unregister its webhook', function () {
+    Telegraph::fake();
+    $bot = make_bot();
+
+    $bot->unregisterWebhook()->send();
+
+    Telegraph::assertUnregisteredWebhook();
+});
+
 it('can register commands', function () {
     Telegraph::fake();
 
diff --git a/tests/Unit/Support/Testing/TelegraphFakeTest.php b/tests/Unit/Support/Testing/TelegraphFakeTest.php
index a5347868..e47735f7 100644
--- a/tests/Unit/Support/Testing/TelegraphFakeTest.php
+++ b/tests/Unit/Support/Testing/TelegraphFakeTest.php
@@ -1,5 +1,7 @@
 <?php
 
+/** @noinspection PhpUnhandledExceptionInspection */
+
 use DefStudio\Telegraph\Facades\Telegraph;
 use PHPUnit\Framework\ExpectationFailedException;
 
@@ -99,6 +101,8 @@ it('fails if the expected data differs from the sent one', function () {
 })->throws(ExpectationFailedException::class, 'Failed to assert that a request was sent to [sendMessage] endpoint with the given data (sent 1 requests so far)');
 
 it('asserts a webhook has been registered', function () {
+    withfakeUrl();
+
     Telegraph::fake();
     $bot = make_bot();
 
@@ -107,6 +111,15 @@ it('asserts a webhook has been registered', function () {
     Telegraph::assertRegisteredWebhook();
 });
 
+it('asserts a webhook has been unregistered', function () {
+    Telegraph::fake();
+    $bot = make_bot();
+
+    Telegraph::bot($bot)->unregisterWebhook()->send();
+
+    Telegraph::assertUnregisteredWebhook();
+});
+
 it('fails if the expected webhook has not been registered', function () {
     Telegraph::fake();
 
diff --git a/tests/__snapshots__/InteractsWithWebhooksTest__it_can_register_a_webhook__1.yml b/tests/__snapshots__/InteractsWithWebhooksTest__it_can_register_a_webhook__1.yml
index 2f1c79ef..f8ef8450 100644
--- a/tests/__snapshots__/InteractsWithWebhooksTest__it_can_register_a_webhook__1.yml
+++ b/tests/__snapshots__/InteractsWithWebhooksTest__it_can_register_a_webhook__1.yml
@@ -1,4 +1,4 @@
 url: 'https://api.telegram.org/bot3f3814e1-5836-3d77-904e-60f64b15df36/setWebhook'
 payload:
-    url: 'http://localhost/telegraph/3f3814e1-5836-3d77-904e-60f64b15df36/webhook'
+    url: 'https://testbot.defstudio.dev/telegraph/3f3814e1-5836-3d77-904e-60f64b15df36/webhook'
 files: {  }
diff --git a/tests/__snapshots__/InteractsWithWebhooksTest__it_can_unregister_a_webhook__1.yml b/tests/__snapshots__/InteractsWithWebhooksTest__it_can_unregister_a_webhook__1.yml
new file mode 100644
index 00000000..6aa68e12
--- /dev/null
+++ b/tests/__snapshots__/InteractsWithWebhooksTest__it_can_unregister_a_webhook__1.yml
@@ -0,0 +1,4 @@
+url: 'https://api.telegram.org/bot3f3814e1-5836-3d77-904e-60f64b15df36/deleteWebhook'
+payload:
+    drop_pending_updates: false
+files: {  }
diff --git a/tests/__snapshots__/InteractsWithWebhooksTest__it_can_unregister_a_webhook_dropping_all_pending_updates__1.yml b/tests/__snapshots__/InteractsWithWebhooksTest__it_can_unregister_a_webhook_dropping_all_pending_updates__1.yml
new file mode 100644
index 00000000..a3da2706
--- /dev/null
+++ b/tests/__snapshots__/InteractsWithWebhooksTest__it_can_unregister_a_webhook_dropping_all_pending_updates__1.yml
@@ -0,0 +1,4 @@
+url: 'https://api.telegram.org/bot3f3814e1-5836-3d77-904e-60f64b15df36/deleteWebhook'
+payload:
+    drop_pending_updates: true
+files: {  }