Compare commits
29 Commits
125bd18e19
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d20702f248 | |||
| 5b5f35e9ce | |||
| fb2a346804 | |||
| 2611701d53 | |||
| c61750285a | |||
| 12280c6d54 | |||
| 6853fbef46 | |||
| 29077ed6d6 | |||
| a162bb2c1f | |||
| 7d26440d0c | |||
| 45a40ae999 | |||
| 266d444922 | |||
| 24360d86b3 | |||
| 5ce8fbd444 | |||
| 82460aa727 | |||
| 4422e7564b | |||
| bcef42b58e | |||
| ea22c19d2b | |||
| c36d83e8b6 | |||
| eb141f00e5 | |||
| 5cd0aea7c8 | |||
| 15c540dcad | |||
| a426d5c6c2 | |||
| 31ac892cbb | |||
| e1a6bd9d42 | |||
| 0849a1fd42 | |||
| 6b5619b232 | |||
| e66e489907 | |||
| d25a7809d2 |
@@ -1,12 +1,34 @@
|
|||||||
name: Push image to registry
|
name: Test, build and push image to registry
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
phpunit-tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
RUNNER_TOOL_CACHE: /toolcache
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '8.3.0'
|
||||||
|
- name: Cache Composer
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.composer/cache
|
||||||
|
key: composer-${{ hashFiles('**/composer.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
composer-
|
||||||
|
- name: Install dependencies
|
||||||
|
run: composer install --prefer-dist --no-progress --no-suggest --no-interaction
|
||||||
|
- name: Run PHPUnit tests
|
||||||
|
run: vendor/bin/phpunit --configuration phpunit.xml
|
||||||
build-image:
|
build-image:
|
||||||
|
needs: phpunit-tests
|
||||||
|
if: success() && github.ref == 'refs/heads/main'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
@@ -17,6 +39,13 @@ jobs:
|
|||||||
registry: git.matthiasg.dev
|
registry: git.matthiasg.dev
|
||||||
username: ninluc
|
username: ninluc
|
||||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
- name: Cache Docker layers (registry-backed)
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: buildx-cache-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
buildx-cache-
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
run: |
|
run: |
|
||||||
docker build -t git.matthiasg.dev/ninluc/datbrowser:latest .
|
docker build -t git.matthiasg.dev/ninluc/datbrowser:latest .
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Browser\Jobs\EldoradoRobuxPriceSentry;
|
||||||
|
|
||||||
|
use App\Models\Job;
|
||||||
|
use App\Notification\Notification;
|
||||||
|
use App\Notification\Stringifiable;
|
||||||
|
use App\Notification\Stringifiable\StringifiableSimpleText;
|
||||||
|
|
||||||
|
class EldoradoRobuxPriceNotification extends Notification {
|
||||||
|
|
||||||
|
private float $price;
|
||||||
|
private float $threshold;
|
||||||
|
private string $link;
|
||||||
|
|
||||||
|
public function __construct(int $jobId, int $price, string $link) {
|
||||||
|
parent::__construct($jobId);
|
||||||
|
|
||||||
|
$this->price = $price;
|
||||||
|
$this->threshold = floatval(Job::find($jobId)->jobInfosTable()->get('eldorado_robux_price_threshold'));
|
||||||
|
$this->link = $link;
|
||||||
|
|
||||||
|
$this->setBody($this->generateBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateBody() {
|
||||||
|
return new EldoradoRobuxPriceNotificationBody($this->price, $this->threshold, $this->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle(): Stringifiable {
|
||||||
|
return new StringifiableSimpleText("Alerte Robux Eldorado 🤑");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getImageProjectPath(): string|null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getLinkURL(): string|null {
|
||||||
|
return $this->link;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Browser\Jobs\EldoradoRobuxPriceSentry;
|
||||||
|
|
||||||
|
use App\Notification\NotificationBody;
|
||||||
|
|
||||||
|
class EldoradoRobuxPriceNotificationBody extends NotificationBody {
|
||||||
|
|
||||||
|
private float $price;
|
||||||
|
private float $threshold;
|
||||||
|
private string $link;
|
||||||
|
|
||||||
|
public function __construct(float $price, float $threshold, string $link) {
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->price = $price;
|
||||||
|
$this->threshold = $threshold;
|
||||||
|
$this->link = $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function toMarkdownString(): string {
|
||||||
|
return "Le prix des Robux sur Eldorado est actuellement de **" . number_format($this->price, 7, ",", " ") . " €**/Robux, ce qui est inférieur ou égal au seuil de **" . number_format($this->threshold, 5, ",", " ") . " €**.\n\n[Voir l'offre sur Eldorado]( " . $this->link . " )";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function toString(): string {
|
||||||
|
return "Le prix des Robux sur Eldorado est actuellement de " . number_format($this->price, 7, ",", " ") . " €/Robux, ce qui est inférieur ou égal au seuil de " . number_format($this->threshold, 5, ",", " ") . " €.\n\nVoir l'offre sur Eldorado : " . $this->link;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ use App\Browser\Jobs\InstagramRepost\DescriptionPipeline\InstagramDescriptionPip
|
|||||||
use App\Models\InstagramNotification;
|
use App\Models\InstagramNotification;
|
||||||
use App\Models\InstagramRepost;
|
use App\Models\InstagramRepost;
|
||||||
use App\Models\Job;
|
use App\Models\Job;
|
||||||
|
use App\Models\JobArtifact;
|
||||||
use App\Models\JobRun;
|
use App\Models\JobRun;
|
||||||
use App\Notification\Notifications\JobDebugNotification;
|
use App\Notification\Notifications\JobDebugNotification;
|
||||||
use App\Notification\Notifications\SimpleNotification;
|
use App\Notification\Notifications\SimpleNotification;
|
||||||
@@ -92,33 +93,46 @@ class EldoradoRobuxPriceSentryJob extends BrowserJob implements ShouldBeUniqueUn
|
|||||||
{
|
{
|
||||||
$lowestPriceElement = $browser->driver->findElement(WebDriverBy::xpath('(//eld-offer-price)[2]/strong'));
|
$lowestPriceElement = $browser->driver->findElement(WebDriverBy::xpath('(//eld-offer-price)[2]/strong'));
|
||||||
$lowestPriceText = $lowestPriceElement->getText(); // Ex: " 0,00478 € "
|
$lowestPriceText = $lowestPriceElement->getText(); // Ex: " 0,00478 € "
|
||||||
$lowestPrice = (float)str_replace(["€", ","], ["", "."], trim($lowestPriceText));
|
$lowestPrice = $this->textToFloat($lowestPriceText);
|
||||||
|
//$lowestPrice = $lowestPrice / 1000; // Price per Robux
|
||||||
|
// TODO : Look at the entire text to try to understand if it is per 1k or per single Robux
|
||||||
|
|
||||||
$threshold = floatval(str_replace(",", ".", $this->jobInfos->get("eldorado_robux_price_threshold")));
|
$threshold = $this->textToFloat($this->jobInfos->get("eldorado_robux_price_threshold"));
|
||||||
dump($threshold);
|
|
||||||
|
|
||||||
Log::info("EldoradoRobuxPriceSentryJob: lowest price = $lowestPrice €, threshold = $threshold €");
|
Log::info("EldoradoRobuxPriceSentryJob: lowest price = $lowestPrice €, threshold = $threshold €");
|
||||||
|
$this->jobRun->addArtifact(new JobArtifact([
|
||||||
|
"name" => "Trouvé le prix le plus bas",
|
||||||
|
"content" => "Prix le plus bas : $lowestPrice €/Robux - Seuil défini : $threshold €/Robux"
|
||||||
|
]));
|
||||||
|
|
||||||
if ($lowestPrice <= $threshold) {
|
if ($lowestPrice <= $threshold) {
|
||||||
$message = "Le prix des Robux sur Eldorado est actuellement de **" . number_format($lowestPrice, 5, ",", " ") . " €**/Robux, ce qui est inférieur ou égal au seuil de **" . number_format($threshold, 5, ",", " ") . " €**.\n\n[Voir l'offre sur Eldorado]( " . self::LINK . " )";
|
|
||||||
$options = [];
|
$options = [];
|
||||||
|
|
||||||
if ($this->jobInfos->get("eldorado_robux_price_discord_webhook") !== null) { // Custom discord webhook
|
if ($this->jobInfos->get("eldorado_robux_price_discord_webhook") !== null) { // Custom discord webhook
|
||||||
$options["discord_webhook_url"] = $this->jobInfos->get("eldorado_robux_price_discord_webhook");
|
$options["discord_webhook_url"] = $this->jobInfos->get("eldorado_robux_price_discord_webhook");
|
||||||
}
|
}
|
||||||
|
|
||||||
AllNotification::send(
|
AllNotification::send(
|
||||||
new SimpleNotification(
|
new EldoradoRobuxPriceNotification(
|
||||||
$this->jobId,
|
$this->jobId,
|
||||||
"Alerte Robux Eldorado 🤑",
|
$lowestPrice,
|
||||||
$message
|
self::LINK
|
||||||
),
|
),
|
||||||
$options
|
$options
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->jobRun->addArtifact(new JobArtifact([
|
||||||
|
"name" => "Envoyé une alerte",
|
||||||
|
"content" => ""
|
||||||
|
]));
|
||||||
|
|
||||||
Log::info("EldoradoRobuxPriceSentryJob: alert sent");
|
Log::info("EldoradoRobuxPriceSentryJob: alert sent");
|
||||||
} else {
|
} else {
|
||||||
Log::info("EldoradoRobuxPriceSentryJob: no alert sent");
|
Log::info("EldoradoRobuxPriceSentryJob: no alert sent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function textToFloat(string $text): float
|
||||||
|
{
|
||||||
|
return floatval(str_replace(["€", ","], ["", "."], trim($text)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ class HellcaseJob extends BrowserJob implements ShouldBeUniqueUntilProcessing
|
|||||||
|
|
||||||
// JobRun
|
// JobRun
|
||||||
// Get the elements text containing class starting with giveaway-entity-prize__
|
// Get the elements text containing class starting with giveaway-entity-prize__
|
||||||
$prizeElement = $browser->driver->findElements(WebDriverBy::xpath('//div[starts-with(@class, "giveaway-entity-prize__")]'));
|
$prizeElement = $browser->driver->findElements(WebDriverBy::xpath('//div[starts-with(@class, "_giveaway_")]//div[contains(@class, "_main_dv7x6_48")]'));
|
||||||
// Join their text
|
// Join their text
|
||||||
$prize = "";
|
$prize = "";
|
||||||
foreach ($prizeElement as $element) {
|
foreach ($prizeElement as $element) {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ abstract class InstagramAbstractJob extends BrowserJob implements ShouldBeUnique
|
|||||||
AllNotification::send(new JobDebugNotification($this->jobId, "Instagram login failed: Incorrect password."));
|
AllNotification::send(new JobDebugNotification($this->jobId, "Instagram login failed: Incorrect password."));
|
||||||
// Stop the job run
|
// Stop the job run
|
||||||
throw new \Exception("Instagram login failed: Incorrect password.");
|
throw new \Exception("Instagram login failed: Incorrect password.");
|
||||||
} catch (\Exception $e) {
|
} catch (\Facebook\WebDriver\Exception\TimeoutException $i) {
|
||||||
// Not the expected error, continue
|
// Not the expected error, continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ abstract class InstagramAbstractJob extends BrowserJob implements ShouldBeUnique
|
|||||||
$popupsTypes = [
|
$popupsTypes = [
|
||||||
['//button[contains(text(), "Allow all cookies")]'], // Allow all cookies
|
['//button[contains(text(), "Allow all cookies")]'], // Allow all cookies
|
||||||
['//button[contains(text(), "Not Now")]', ["Popup Not Now clicked"]], // Not now
|
['//button[contains(text(), "Not Now")]', ["Popup Not Now clicked"]], // Not now
|
||||||
['//button[contains(text(), "OK")]', ["Popup Ok clicked"]], // OK
|
['(//button|//div)[contains(text(), "OK")]', ["Popup Ok clicked"]], // OK
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($popupsTypes as $popup) {
|
foreach ($popupsTypes as $popup) {
|
||||||
@@ -119,9 +119,9 @@ abstract class InstagramAbstractJob extends BrowserJob implements ShouldBeUnique
|
|||||||
}
|
}
|
||||||
$button->click();
|
$button->click();
|
||||||
sleep(2);
|
sleep(2);
|
||||||
return; // Exit after clicking the first popup found
|
//return; // Exit after clicking the first popup found
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// Porbably no popup found, continue
|
// Probably no popup found, continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ class InstagramRepostJob extends InstagramAbstractJob implements ShouldBeUniqueU
|
|||||||
sleep(2);
|
sleep(2);
|
||||||
$this->signin($browser);
|
$this->signin($browser);
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
$this->removePopups($browser);
|
||||||
|
sleep(2);
|
||||||
$this->repostLatestPosts($browser);
|
$this->repostLatestPosts($browser);
|
||||||
sleep(5);
|
sleep(5);
|
||||||
|
|
||||||
@@ -449,6 +451,7 @@ Captions must:
|
|||||||
4. Encourage engagement relevant to the platform's algorithm (e.g., asking a question related to the joke/scene).
|
4. Encourage engagement relevant to the platform's algorithm (e.g., asking a question related to the joke/scene).
|
||||||
5. Optionally include relevant hashtags at the end (#hashtagsOnly), chosen appropriately for the reel's content or vibe. Use common tags if no specific ones are provided, but avoid overly generic ones unless fitting.
|
5. Optionally include relevant hashtags at the end (#hashtagsOnly), chosen appropriately for the reel's content or vibe. Use common tags if no specific ones are provided, but avoid overly generic ones unless fitting.
|
||||||
6. If credit information is provided in the input (e.g., `credit: twitteruser`), acknowledge it minimally within the caption text *using only that source*. Do not invent any account handles (`@`) or platform prefixes (`tt/`). Use phrases like \"Credited to...\" or simply insert the credited name if appropriate, but don't force it unless the core concept naturally includes attribution. If no credit is provided, do not mention a specific creator.
|
6. If credit information is provided in the input (e.g., `credit: twitteruser`), acknowledge it minimally within the caption text *using only that source*. Do not invent any account handles (`@`) or platform prefixes (`tt/`). Use phrases like \"Credited to...\" or simply insert the credited name if appropriate, but don't force it unless the core concept naturally includes attribution. If no credit is provided, do not mention a specific creator.
|
||||||
|
7. Be in english.
|
||||||
|
|
||||||
**Do Not:**
|
**Do Not:**
|
||||||
* Start captions with 'This reel...' or similar intros.
|
* Start captions with 'This reel...' or similar intros.
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
|
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
|
||||||
<env name="BCRYPT_ROUNDS" value="4"/>
|
<env name="BCRYPT_ROUNDS" value="4"/>
|
||||||
<env name="CACHE_STORE" value="array"/>
|
<env name="CACHE_STORE" value="array"/>
|
||||||
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
|
<env name="DB_CONNECTION" value="sqlite"/>
|
||||||
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
|
<env name="DB_DATABASE" value=":memory:"/>
|
||||||
<env name="MAIL_MAILER" value="array"/>
|
<env name="MAIL_MAILER" value="array"/>
|
||||||
<env name="PULSE_ENABLED" value="false"/>
|
<env name="PULSE_ENABLED" value="false"/>
|
||||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const jobInfoType = props.jobInfo.job_info_type.name;
|
|||||||
<Label :for="'' + jobInfo.id" class="text">{{ jobInfo.name }}<span v-if="jobInfo.is_required" class="cursor-help" title="Requis" aria-label="Requis">*</span></Label>
|
<Label :for="'' + jobInfo.id" class="text">{{ jobInfo.name }}<span v-if="jobInfo.is_required" class="cursor-help" title="Requis" aria-label="Requis">*</span></Label>
|
||||||
<Description>{{ jobInfo.description }}</Description>
|
<Description>{{ jobInfo.description }}</Description>
|
||||||
<Input v-if="['text', 'email', 'password', 'url', 'number'].includes(jobInfoType)" :type="jobInfoType" :id="'' + jobInfo.id" :name="'' + jobInfo.id" :placeholder="jobInfo.placeholder" v-model="jobInfo.value as string" :required="jobInfo.is_required" />
|
<Input v-if="['text', 'email', 'password', 'url', 'number'].includes(jobInfoType)" :type="jobInfoType" :id="'' + jobInfo.id" :name="'' + jobInfo.id" :placeholder="jobInfo.placeholder" v-model="jobInfo.value as string" :required="jobInfo.is_required" />
|
||||||
<Input v-else-if="jobInfoType == 'decimal'" :type="jobInfoType" :id="'' + jobInfo.id" :name="'' + jobInfo.id" :placeholder="jobInfo.placeholder" v-model="jobInfo.value as number" step="any" :required="jobInfo.is_required" />
|
<Input v-else-if="jobInfoType == 'decimal'" :type="jobInfoType" :id="'' + jobInfo.id" :name="'' + jobInfo.id" :placeholder="jobInfo.placeholder" v-model="jobInfo.value as string" step="any" :required="jobInfo.is_required" />
|
||||||
<VModelCheckbox v-else-if="jobInfoType == 'boolean'" :id="'' + jobInfo.id" v-model="jobInfo.value as boolean" />
|
<VModelCheckbox v-else-if="jobInfoType == 'boolean'" :id="'' + jobInfo.id" v-model="jobInfo.value as boolean" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -28,5 +28,5 @@ Schedule::job(new HellcaseJob)->daily()->onOneServer()->withoutOverlapping()->na
|
|||||||
Schedule::job(new HellcaseBattlesJob)->hourly()->onOneServer()->withoutOverlapping()->name('hellcase_battles')->description('Hellcase battles job');
|
Schedule::job(new HellcaseBattlesJob)->hourly()->onOneServer()->withoutOverlapping()->name('hellcase_battles')->description('Hellcase battles job');
|
||||||
Schedule::job(new InstagramRepostJob)->everyThreeHours()->onOneServer()->withoutOverlapping()->name('instagram_reposts')->description('Instagram reposts job');
|
Schedule::job(new InstagramRepostJob)->everyThreeHours()->onOneServer()->withoutOverlapping()->name('instagram_reposts')->description('Instagram reposts job');
|
||||||
Schedule::job(new InstagramNotificationHandlingJob)->hourly()->onOneServer()->withoutOverlapping()->name('instagram_reposts_notifications')->description('Instagram reposts notification handling job');
|
Schedule::job(new InstagramNotificationHandlingJob)->hourly()->onOneServer()->withoutOverlapping()->name('instagram_reposts_notifications')->description('Instagram reposts notification handling job');
|
||||||
Schedule::job(new EldoradoRobuxPriceSentryJob)->dailyAt("14:00")->onOneServer()->withoutOverlapping()->name('eldorado_robux_price_sentry')->description('Eldorado Robux Price Sentry job');
|
Schedule::job(new EldoradoRobuxPriceSentryJob)->hourlyAt(20)->onOneServer()->withoutOverlapping()->name('eldorado_robux_price_sentry')->description('Eldorado Robux Price Sentry job');
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\EldoradoRobuxPriceSentryJob;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Foundation\Testing\WithFaker;
|
||||||
|
use App\Browser\Jobs\EldoradoRobuxPriceSentry\EldoradoRobuxPriceSentryJob;
|
||||||
|
use ReflectionMethod;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class textToFLoatTest extends TestCase
|
||||||
|
{
|
||||||
|
private EldoradoRobuxPriceSentryJob $job;
|
||||||
|
|
||||||
|
protected function setUp(): void {
|
||||||
|
parent::setUp();
|
||||||
|
$this->job = new EldoradoRobuxPriceSentryJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function assertTextToFloat($input, $expected) {
|
||||||
|
$reflection = new ReflectionMethod(EldoradoRobuxPriceSentryJob::class, 'textToFloat');
|
||||||
|
$reflection->setAccessible(true);
|
||||||
|
$result = $reflection->invoke($this->job, $input);
|
||||||
|
$this->assertEquals($expected, $result, "Failed asserting that textToFloat('$input') equals $expected. Got $result instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function test_simple_int(): void
|
||||||
|
{
|
||||||
|
$this->assertTextToFloat("10", 10.0);
|
||||||
|
$this->assertTextToFloat(" 42", 42.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_decimal_numbers(): void
|
||||||
|
{
|
||||||
|
$this->assertTextToFloat("3,14", 3.14);
|
||||||
|
$this->assertTextToFloat(" 0,0015 ", 0.0015);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_money_symbols_int(): void
|
||||||
|
{
|
||||||
|
$this->assertTextToFloat("5 €", 5.0);
|
||||||
|
$this->assertTextToFloat(" € 123 ", 123.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_money_symbols_decimal(): void
|
||||||
|
{
|
||||||
|
$this->assertTextToFloat("7,89 €", 7.89);
|
||||||
|
$this->assertTextToFloat(" € 0,75 ", 0.75);
|
||||||
|
$this->assertTextToFloat(" €0.00402 ", 0.00402);
|
||||||
|
$this->assertTextToFloat(" 0,00429 € ", 0.00429);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
0
tests/Unit/.gitkeep
Normal file
0
tests/Unit/.gitkeep
Normal file
13
undetectedChromedriver/README.md
Normal file
13
undetectedChromedriver/README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Selenium Undetected Standalone-Chromedriver
|
||||||
|
|
||||||
|
Selenium Standalone-Chromedriver with Undected-Chromedriver applied
|
||||||
|
|
||||||
|
## Bug
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Could not start a new session. Response code 500. Message: session not created: probably user data directory is already in use,
|
||||||
|
```
|
||||||
|
|
||||||
|
Go into the `/home/seluser` director in the container and run `rm -rf ~/.config/google-chrome/Singleton*`
|
||||||
|
|
||||||
|
If it doesn't work, the log can be found in the set profile folder in the file `chrome_debug.log`
|
||||||
Reference in New Issue
Block a user