|
56415
|
1966
|
17
|
2026-05-19T08:05:55.753410+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177955753_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3921796768863820486
|
-8634233732034220862
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obEDHomeDMsActivityFilesLaterMoreJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily - in 3 h 55 m100% C3• Tue 19 May 11:05:55QDescribe what you are looking for# the_people_of jimi...8 426 0• Messages@ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4Message #the_people_of_jiminny+...
|
56412
|
NULL
|
NULL
|
NULL
|
|
56417
|
1966
|
18
|
2026-05-19T08:05:59.104802+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177959104_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1655837267692718254
|
-9140731314152200412
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56418
|
1967
|
21
|
2026-05-19T08:05:59.120780+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177959120_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1356238323261734672
|
-8996598804339809755
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56420
|
1967
|
22
|
2026-05-19T08:05:59.734955+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177959734_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1655837267692718254
|
-9140731314152200412
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options...
|
56418
|
NULL
|
NULL
|
NULL
|
|
56419
|
1966
|
19
|
2026-05-19T08:05:59.773080+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177959773_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
56417
|
NULL
|
NULL
|
NULL
|
|
56421
|
1967
|
23
|
2026-05-19T08:06:02.304679+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177962304_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56422
|
1967
|
24
|
2026-05-19T08:06:02.892711+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177962892_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-8334616115047382362
|
-9140749176787754460
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error...
|
56421
|
NULL
|
NULL
|
NULL
|
|
56424
|
1967
|
25
|
2026-05-19T08:06:05.812954+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177965812_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-351575931525056321
|
-8132358351805502526
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
PhostormProiectVIewINavicareCodeLaravelKeractorTOOISWindowFV faVsco.js?9 JY-20676-delete-report-related-objectsC) AutomatedReport.onp© AskAnythingPromptServiceTest.php= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]& console [EU]- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php X© AskAnythingPromptDto.phpA console [STAGING)© CoachingFeedbackCoachUserln.php Xe) -xooricontro||erRateLimit est.onoC) FakeProphetClient.ohv> _ Midd eware• → Requests© AskAnythingPromptService.phg© BaseService.phpfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~© SoftPhoneManager.phpC) RoleAttr.png© ScimProvisioning.phppubuic tunccion conscruccuserkeposicory suserkeposicorw...© CoreUser.phd() ListenerRoleCannotHaveAdminOrMa() RoleAttrTest.php29 6tpublic function shouldApplyQueries: bool{...}InvitationsIHlohsIn ListenersD McpN ModelsiM NotificationsD OrganizationSettingsD PlaylistsD Policies( RepositoriesC RulesC SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search›_ serviceProvidersListenerRoleCannotHaveAdminOrManagerPermissionRule.php© Activity/Close/Service.php©) Activity/RinqCentral/Service.php34 6t >public function getQueries: FilterDefinition0ueryCollection{...}© SyncActivity.php© Crm/Close/Service.php(C) TextMessaqingService.phpfinal class SavedSearchCRUDFeatureTest extends TestCaseA3416 ^ v45 6touolic function toArravo: arrav..."194 D >public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}1 usaad#Phrun1c rramework Accribuces lescpublic function userCanDeleteASavedSearch: void{...}private function getOptions: arrayt...257 D >314118public function getValue: arrayt...130=131135136 >lusageprivate function getDefaultValue: arrayt...public function getValidationRules(?string $prefix = null): array{...}Console XLooX©O ActivityController.php app/Htte/Controllers/AP© AskAnythingPrompt.php app/Models/AskAnything© AskAnvthinaPromptDto.php app/Component/AskAnvthina/Dtos© AskAnvthinaPromptService.php app/Component/AskAnvthing@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2T.OCurrent version app/Rules/Lis<2ohnDo not ignoreHighlight words ?declanp ctrict +vnec=1)+namesnace Liminnv Rules.C) Constants.ono apo/Comoonent/SClMI© CoreUser.php app/DTO/SCIM/AAD/ResponseC) CoreUserRequest.ono aoo/DTO/SCIMIAAD/[EMAIL] app/Console/Commandsphp logging.php configScimProvisioning.php app/Component/SCIM(C) Search.oho aon/Models/Activitviuse Closure:use Illuminate \Contracts \Validation ValidationRule:use ILLuminace support collecclonuse Illuminate\Translation\PotentiallyTranslatedStringuse Jiminny nodels kole'Unversioned Files 13 filesuse Jiminny nodels user.env.nikilocal appE .env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicE ids.txt app* ListenerRoleCannotHaveAdminOrManagerPermissionRule.php app/RulesQit LictonerPoleCannotHaveAdminOrManaqerPermissionRuleTest.php tests/Ta raw sal_query.sal app© RoleAttr.php app/Component/SCIM/Mutators/Attributes/Use°) RoleAttrTest.php tests/Unit/Co© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK FILTERING_IMPLEMENTATION.md apdfinal readonly class ListenerRoleCannotHaveAdmin0rManagerPermissionRule implements ValidationRulepublic function construct(/** @var Collection<Role> */orivate collection sroles.* @param int[] $valve* Gparam Closure(strina): PotentialutranstatedStrina Sfoalpublic function validate(string $attribute, mixed $value, Closure $fail): voidThe Hunspell plugin has been deprecated. If you're not writing in Hungarian, you can safely uninstall Hunspell without affecting the dictionaries for other languages. (today 10:00)"suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:05U AskJiminnyReportActivityServiceTest v+0 ..CascadeAsk Jiminny Report Mmocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 - In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload (['ask_anything_prompt_id' = null, 'status' = falsel ).Per your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.odl "* Reject allAccept all8 files 400-7 )Ask anvthing (*4D+ <> Code Claude Opus 4.7 MediumW Windsurf Teams 314:1 UTF-8 P 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56423
|
1966
|
20
|
2026-05-19T08:06:05.821541+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177965821_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"}]...
|
3224510618648346242
|
-8132287982927107134
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obEDHomeDMsActivityFilesLaterMoreJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:05QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A687Message #the_people_of_jiminny+...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56425
|
1967
|
26
|
2026-05-19T08:06:08.920287+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177968920_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1356238323261734672
|
-8996598804339809755
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
56424
|
NULL
|
NULL
|
NULL
|
|
56426
|
1966
|
21
|
2026-05-19T08:06:09.913283+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177969913_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-2078138591382873457
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All...
|
56423
|
NULL
|
NULL
|
NULL
|
|
56428
|
1967
|
27
|
2026-05-19T08:06:09.958178+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177969958_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6870583155641010293
|
-8132287983061324858
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
PhpStormViewNavigateCodeLaravelRefactorTOOISWindowFV faVsco.jsv?9 JY-20676-delete-report-related-objectsProiect vC) AutomatedReport.onp© AskAnythingPromptServiceTest.php© ActivityAskAnythinglest.phpe) -xooricontro||erRateLimit est.ono© SavedSearchCRUDFeatureTest.php X© AskAnythingPromptDto.phpC)FakeProphetClient.oho© AskAnythingPromptService.ph© BaseService.phpMidd lewareM RequestsSoftPhoneManager.phpC) RoleAttr.png© ScimProvisioning.php() ListenerRoleCannotHaveAdminOrMa() RoleAttrTest.phpInteractionsInvitationsalobs" ListenerRoleCannotHaveAdminOrManagerPermissionRule.php© Activity/Close/Service.php©) Activity/RinqCentral/Service.phpListeners© SyncActivity.php© Crm/Close/Service.php(C) TextMessaqingService.phpD McpModelsD NotificationsD OrganizationSettingsD PlaylistsD Policies( RepositoriesC Rules0 SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search> C ServiceProvidersfinal class SavedSearchCRUDFeatureTest extends TestCase194 D >255256257 D >314public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}#[\PHPUnit\Framework\Attributes\Test]public function userCanDeleteASavedSearch: void{...}Local ChandesConsole XLooXv Changes 18 files=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnything© AskAnvthinaPromptDto.php app/Component/AskAnvthina/Dtos© AskAnythingPromptService.php app/Component/AskAnything@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2T.O©® Side-by-side viewerCurrent version raw sal querv.sallDo not ignoreHighlight words ?SELECT activities. *C) Constants.ono apo/Comoonent/SClM© CoreUser.php app/DTO/SCIM/AAD/ResponseC) CoreUserRequest.ono aoo/DTO/SCIMIAAD/Requesi© JiminnyDebugCommand.php app/Console/CommandsC ListenerRoleCannotHaveAdminOrManagerPermissionRule.php app/Rules@* ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Unit/FFROM activitiesINNER JOIN activity_processing_states AS aps ON aps.activity_id = activities.idINNER JOIN users ON users.id = activities.user_idWHERE activities.is_internal = 0AND users.status = 1AND activities.type NOT IN ('email_inbound', 'email_outbound',AND aps.state = 'send_processing_notificationsAND aps.status IN ('finished', 'failed')AND aps.created_at BETWEEN ? AND ?AND aps.deleted_at IS NULL-- Optional team filter (add when teamId is provided):-- AND users.team id = ?php logging.php config© RoleAttr.php app/Component/SCIM/Mutators/Attributes/Usec) RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/Use@ ScimProvisioning.php app/Component/SCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt appT raw sal querv.sal apn© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotMJ WEBHOOK FILTERING IMPLEMENTATION.md annThe Hunspell plugin has been deprecated. If you're not writing in Hungarian, you can safely uninstall Hunspell without affecting the dicries for other languages. (today 10:00)"suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:09U AskJiminnyReportActivityServiceTest v+0 ..= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]& console [EU]A console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~29 6t34 6t >A3416 ^ v45 6t- 119- 131135136 >public function construct(UserRepository SuserRepository){...}public function shouldApplyQueries: bool{...}public function getQueries: FilterDefinitionQueryCollection{...}ouolic function toArravo: arrav...?1 usaadprivate function getOptions: arrayt...public function getValue: arrayt...lusageprivate function getDefaultValue: arrayt...public function getValidationRules(?string $prefix = null): array{...}CascadeAsk Jiminny Report Mmocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['ask_anything_prompt_id' = null, 'status' = falsel ).Per your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.8 files 400-7 )Ask anvthina (4D1+ <> Code Claude Opus 4.7 Medium* Reject allAccept allW Windsurf Teams 314:1 UTF-8 P 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56427
|
1966
|
22
|
2026-05-19T08:06:10.575002+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177970575_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56430
|
1966
|
23
|
2026-05-19T08:06:11.007655+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177971007_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7900466997463401669
|
-5826444973847630902
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obEDHomeDMsActivityFilesLaterMoreJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:10QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A687Message #the_people_of_jiminny+...
|
56427
|
NULL
|
NULL
|
NULL
|
|
56429
|
1967
|
28
|
2026-05-19T08:06:11.621779+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177971621_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1356238323261734672
|
-8996598804339809755
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
56428
|
NULL
|
NULL
|
NULL
|
|
56431
|
1966
|
24
|
2026-05-19T08:06:13.015829+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177973015_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56432
|
1967
|
29
|
2026-05-19T08:06:13.018092+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177973018_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56433
|
1967
|
30
|
2026-05-19T08:06:13.768774+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177973768_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"}]...
|
7416589213088100201
|
-8996616126076344540
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project...
|
56432
|
NULL
|
NULL
|
NULL
|
|
56434
|
1967
|
31
|
2026-05-19T08:06:14.764810+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177974764_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56435
|
1966
|
25
|
2026-05-19T08:06:16.356352+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177976356_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6966022010367698874
|
-564708849257816637
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obEDHomeDMsActivityFilesLaterMoreJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:16QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A687Message #the_people_of_jiminny+...
|
56431
|
NULL
|
NULL
|
NULL
|
|
56436
|
1967
|
32
|
2026-05-19T08:06:16.376487+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177976376_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5235617535283860069
|
-8132292381107834938
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
iilPhostormVIewINavicareCodeLaravelKeractorTOOISFV faVsco.js°9 JY-20676-delete-report-related-objectsProiectC) AutomatedReport.onp© AskAnythingPromptServiceTest.php- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php X© AskAnythingPromptDto.phpe) -xooricontro||erRateLimit est.onoC) FakeProphetClient.ohv© BaseService.php> _ Midd ewareC SoftPhoneManager.phpC) RoleAttr.png© ScimProvisioning.phpRequests() ListenerRoleCannotHaveAdminOrMa() RoleAttrTest.phpInteractionsInvitationsListenerRoleCannotHaveAdminOrManagerPermissionRule.phpC) Activity/Close/Service.php© Activity/RingCentral/Service.phpIHlobsListeners© SyncActivity.php© Crm/Close/Service.php(C) TextMessaqingService.phpD McpN Modelsifinal class SavedSearchCRUDFeatureTest extends TestCase194 D >public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}M NotificationsD OrganizationSettingsD PlaylistsD Policies257 D >#Phrun1c rramework Accribuces lescpublic function userCanDeleteASavedSearch: void{...}314_ kepositonesC RulesC SavedSearchesSavedSearchCRUDFeatureTest.php› C Search›_ serviceProvidersConsole XLoo Xv Changes 18 files=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnythingc) AsKAnvihinaPromotbto.ono apo/comoonent/AskAnvihino/Dros© AskAnvthinaPromptService.php app/Component/AskAnvthina@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/APIV2→© Side-by-side viewerDo not ignoreHighlight wordsx 158 5604af40 app/Compuse Jiminny Models Role:use liminnv Model c Team:use Jiminny Models\User;use liminnv Senvices IlsenSenvice.use Sentry:C) Constants.ono aoo/CC) Coreuser.ono aoo/DIO/SCIMIAAD/Resoonseclass ScimProvisioningC) CoreUserRequest.ono ano/DTO/SCIMIAAD/Request© JiminnyDebugCommand.php app/Console/Commands@ ListenerRoleCannotHaveAdminOrManagerPermissionRule.pho apn/RulesQ ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Urpublic function _construct(private readonly Dispatcher SeventDispatcherphp loadina.nho confialorivace readonly userservice suserserviceprivate readonly RoleChangeLogger SroleChangeLoggerC RoleAttr.nho aoo/Comnonent/SCIM/Mutators/Attributes/Use') RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/UseriC CcimDrovicionina nhn ann/Camnonent/CCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt apdTraw saL querv.sal app© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK FILTERINGIMPLEMENTATION.md aprpublic function validateUserIdInput($id, Team Steam): boolT'email' => Sdto->qetEmailPrimaryWorkO],SuserUodateDatalif (! SnewUser->roles()->exists()) {Snewliser->addRole User: ROLE ANALYSTO:/** @var Role Srole */Snole = Role• •quervo->whenedr'namel => Isen• •ROI F ANAI VSTD->finctinSailo•Tihe Hunsnelinluain has been denrecated lfivouire not writinalin ungarian vou can safelvmninstalllHunsnellwithout affectina the diationaries for athez lanauades /today 10:00= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~pubLic tunccion conscruct userkeposicory suserkeposicorw?...29 6tpublic function shouldApplyQueries: bool{...}34 6t >public function getQueries: FilterDefinitionQueryCollection{...}A3416 ^ v45 6tpubLic function toArray): arrayl...л1 usaadprivate function getOptions: arrayt...=119=130public function getValue: arrayt...=131lusageprivate function getDefaultValue: arrayt...Ask anvthina (4D1136 >public function getValidationRules(?string $prefix = null): array{...}4 @s Codo Chudo Onuc 17 ModiumCurrent versionuse Jiminny Models Role;use liminnv Model c Teamuse Jiminny Models\User;luse liminnv Senvices IlcenSenvico•use Jiminny\Contracts\Acl \RoleRepositoryInterface:use Illuminate\Support\Facades|VaLidaton.use Jiminny Rules\DependentRolesRule:use Jiminny Rules\ListenerRoleCannotHaveAdmin0rManagerPermissionRule:use Jiminny Rules \ListenerRoleRequiresListenerFeatureRuleuse Jiminny Actions UpdateUserRolesAction:use Jiminny DTO\Roles UserRolesSyncDT0:use Sentry:class Sc1mProv1s10n1nqlpublic function -_constructorivate readonly Daspatcher seventiisoatcher.private readonly UserService $userService,orivate readonly RolechangeLogger SroleChangeLogger..orivate readonly RoleRepositoryInterface $roleRepository,orivate readoniv UodatelserRolesAction SundatelserRolesAction.nublic function validatellsenTdinnut(Sid. Team Steam• hooll• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:16AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report M+0 ..3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt id is nult. Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alli•01.4 difterencesWN Windsurf Toams 214-1UTF.8ih 4 spaces...
|
56434
|
NULL
|
NULL
|
NULL
|
|
56437
|
1967
|
33
|
2026-05-19T08:06:18.458477+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177978458_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56439
|
1967
|
34
|
2026-05-19T08:06:21.347599+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177981347_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.22426178,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.22426178,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.22266561,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.22266561,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
1356238323261734672
|
-8996598804339809755
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}...
|
56437
|
NULL
|
NULL
|
NULL
|
|
56438
|
1966
|
26
|
2026-05-19T08:06:21.384837+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177981384_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
4508586470331655935
|
-8996598804337712604
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56440
|
1967
|
35
|
2026-05-19T08:06:22.053879+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177982053_m2.jpg...
|
PhpStorm
|
Shelve Changes
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Diff
Changelist:
Changelist:
Changes
Show Diff
Rol Diff
Changelist:
Changelist:
Changes
Show Diff
Rollback...
Refresh
Group By...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Diff","depth":1,"bounds":{"left":0.25531915,"top":0.39185953,"width":0.013962766,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Changelist:","depth":1,"bounds":{"left":0.51329786,"top":0.15802075,"width":0.022938829,"height":0.027134877},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Changelist:","depth":1,"bounds":{"left":0.5375665,"top":0.15802075,"width":0.042220745,"height":0.027134877},"on_screen":true,"role_description":"pop up button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Changes","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Show Diff","depth":2,"bounds":{"left":0.25664893,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Rollback...","depth":2,"bounds":{"left":0.26529256,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Refresh","depth":2,"bounds":{"left":0.27393618,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Group By","depth":2,"bounds":{"left":0.28490692,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8548744354360513343
|
-9095604003377772283
|
visual_change
|
hybrid
|
NULL
|
Diff
Changelist:
Changelist:
Changes
Show Diff
Rol Diff
Changelist:
Changelist:
Changes
Show Diff
Rollback...
Refresh
Group By
iilPhostormINavicareCodeKeractorTOOISFV faVsco.js°9 JY-20676-delete-report-related-objectsProiect vC) AutomatedReport.onp© AskAnythingPromptServiceTest.php- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php X© AskAnythingPromptDto.phpe) -xooricontro||erRateLimit est.onoC) FakeProphetClient.ohv© BaseService.php> _ Midd ewareC SoftPhoneManager.pnpC) RoleAttr.png© ScimProvisioning.phpRequests() ListenerRoleCanr() RoleAttrTest.phpInteractionsInvitationsListenerRoleCannotHaveAdminOrManagerPermissionRule.phpC)Activity/Close/Service.php© Activity/RingCentral/Service.phpIHlobsListeners© SyncActivity.php© Crm/Close/Service.php(C) TextMessaqingService.phpD McpN Modelsifinal class SavedSearchCRUDFeatureTest extends TestCase194 D >public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}M NotificationsD OrganizationSettingsW rlayllstsD Policies257 D >#Phrun1c rramework Accribuces lescpublic function userCanDeleteASavedSearch: void{...}314_ kepositonesC RulesC SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search›_ serviceProvidersLocal ChandesConsole XLooXChanges 18 tlles=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnythingc) AsKAnvihinaPromotbto.ono apo/comoonent/AskAnvihino/Dros© AskAnvthinaPromptService.php app/Component/AskAnvthing@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2Side-by-side viewerDo not ignoreHighlight words 158 5604af40 app/Compuse Jiminny Models Role:use liminnv Model c Team:use Jiminny Models\User;use liminnv Senvices IlsenSenvice.use Sentry:C) Constants.ono aoo/CC) Coreuser.ono aoo/DIO/SCIMIAAD/Resoonseclass ScimProvisioningC) CoreUserRequest.ono ano/DTO/SCIMIAAD/Requesti© JiminnyDebugCommand.php app/Console/Commands@ ListenerRoleCannotHaveAdminOrManagerPermissionRule.pho apn/RulesQ ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Unpublic function _construct(private readonly Dispatcher SeventDispatcherphp loadina.nho confialorivace readonly userservice suserserviceprivate readonly RoleChangeLogger SroleChangeLogger© RoleAttr.php app/Component/SCIM/Mutators/Attributes/Use) RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/UseriC CcimDrovicionina nhn ann/Camnonent/CCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt apdTraw sal qauerv.sal app© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK FILTERINGIMPLEMENTATION.md aprpublic function validateUserIdInput($id, Team Steam): bool['email' => $dto->getEmailPrimaryWork)],SuserUodateDatalif (! SnewUser->roles()->exists()) {Snewliser->addRole User: ROLE ANALYSTO:/** @var Role Srole */Snole = Role• •quervo->whenedr'namel => Isen• •ROI F ANAI VSTD->finctinSailo•Tihe Hunsnelinluain has been denrecated lfivouire not writinalin ungarian vou can safelvmninstalllHunsnellwithout affectina the diationaries for athez lanauades /today 10:00= custom.log= laravel.log« SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~pubLic tunccion conscruct userkeposicory suserkeposicorw?...29 6tpublic function shouldApplyQueries: bool{...}34 6t >public function getQueries: FilterDefinitionQueryCollection{...}A3416 ^ v45 6tpubLic function toArrayo): arrayi...h1 usaadprivate function getOptions: arrayt...=119=130public function getValue: arrayt...=131lusageprivate function getDefaultValue: arrayt...Ask anvthina (4D1136 >public function getValidationRules(?string $prefix = null): array{...}4 @s Codo Chudo Onuc 17 ModiumCurrent versionuse Jiminny Models Role;use liminnv Model c Teamuse Jiminny Models\User;luse liminnv Senvices IlcenSenvico•use Jiminny\Contracts\Acl \RoleRepositoryInterface:use Illuminate\Support\Facades|VaLidaton.use Jiminny Rules\DependentRolesRule;use Jiminny Rules\ListenerRoleCannotHaveAdmin0rManagerPermissionRule:use Jiminny Rules \ListenerRoleRequiresListenerFeatureRuleuse Jiminny Actions UpdateUserRolesAction:use Jiminny DTO\Roles UserRolesSyncDT0:use Sentry:class Sc1mProv1s10n1nqlpublic function -_constructorivate readonly Daspatcher seventiisoatcher.private readonly UserService $userService,orivate readonly RolechangeLogger SroleChangeLogger..orivate readoniv UodatelserRolesAction SundatelserRolesAction.nublic function validatellsenTdinnut(Sid. Team Steam• hooll• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:21AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report M+0 ..3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt id is nult. Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alli•01.4 difterencesWN Windsurf Toams 214-1UTF.8ih 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56441
|
1967
|
36
|
2026-05-19T08:06:25.094506+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177985094_m2.jpg...
|
PhpStorm
|
Shelve Changes
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Diff
Changelist:
Changelist:
Changes
Show Diff
Rol Diff
Changelist:
Changelist:
Changes
Show Diff
Rollback...
Refresh
Group By
Expand All
Collapse All
18 files, folder partially checked
app 13 files, folder partially checked
Component 5 files, folder partially checked
AskAnything 2 files, folder not checked
SCIM 3 files, folder checked
Mutators/Attributes/User 1 file, folder checked
RoleAttr.php, class checked
Constants.php, class checked
ScimProvisioning.php, class checked
Console/Commands 1 file, folder not checked
DTO/SCIM/AAD 2 files, folder checked
Request 1 file, folder checked
CoreUserRequest.php, class checked
Response 1 file, folder checked
CoreUser.php, class checked
Http/Controllers/API 2 files, folder not checked
Models 2 files, folder not checked
Rules 1 file, folder checked
ListenerRoleCannotHaveAdminOrManagerPermissionRule.php, final class checked
config 1 file, folder not checked
tests/Unit 3 files, folder partially checked
Component 2 files, folder partially checked
AskAnything 1 file, folder not checked
SCIM/Mutators/Attributes/User 1 file, folder checked
RoleAttrTest.php, final class checked
Rules 1 file, folder checked
ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.php, final class checked
.env.local not checked
app 13 files, folder partially checked
Component 5 files, folder partially checked
AskAnything 2 files, folder not checked
SCIM 3 files, folder checked
Mutators/Attributes/User 1 file, folder checked
RoleAttr.php, class checked
Constants.php, class checked
ScimProvisioning.php, class checked
Console/Commands 1 file, folder not checked
DTO/SCIM/AAD 2 files, folder checked
Request 1 file, folder checked
CoreUserRequest.php, class checked
Response 1 file, folder checked
CoreUser.php, class checked
Http/Controllers/API 2 files, folder not checked
Models 2 files, folder not checked
Rules 1 file, folder checked
ListenerRoleCannotHaveAdminOrManagerPermissionRule.php, final class checked
Component 5 files, folder partially checked
AskAnything 2 files, folder not checked
SCIM 3 files, folder checked
Mutators/Attributes/User 1 file, folder checked
RoleAttr.php, class checked
Constants.php, class checked
ScimProvisioning.php, class checked
AskAnything 2 files, folder not checked...
|
[{"role":"AXStaticText","text& [{"role":"AXStaticText","text":"Diff","depth":1,"bounds":{"left":0.25531915,"top":0.39185953,"width":0.013962766,"height":0.013567438},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Changelist:","depth":1,"bounds":{"left":0.51329786,"top":0.15802075,"width":0.022938829,"height":0.027134877},"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Changelist:","depth":1,"bounds":{"left":0.5375665,"top":0.15802075,"width":0.042220745,"height":0.027134877},"on_screen":true,"role_description":"pop up button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Changes","depth":6,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Show Diff","depth":2,"bounds":{"left":0.25664893,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Rollback...","depth":2,"bounds":{"left":0.26529256,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Refresh","depth":2,"bounds":{"left":0.27393618,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Group By","depth":2,"bounds":{"left":0.28490692,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand All","depth":2,"bounds":{"left":0.49268618,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":2,"bounds":{"left":0.5013298,"top":0.16201118,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"18 files, folder partially checked","depth":4,"bounds":{"left":0.26462767,"top":0.0981644,"width":0.032247342,"height":0.017557861},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"app 13 files, folder partially checked","depth":5,"bounds":{"left":0.27094415,"top":0.11572227,"width":0.040226065,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Component 5 files, folder partially checked","depth":6,"bounds":{"left":0.27726063,"top":0.13328013,"width":0.05418883,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"AskAnything 2 files, folder not checked","depth":7,"bounds":{"left":0.2835771,"top":0.15083799,"width":0.05618351,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"SCIM 3 files, folder checked","depth":7,"bounds":{"left":0.2835771,"top":0.16839585,"width":0.041223403,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mutators/Attributes/User 1 file, folder checked","depth":8,"bounds":{"left":0.28989363,"top":0.1859537,"width":0.0787899,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"RoleAttr.php, class checked","depth":9,"bounds":{"left":0.2962101,"top":0.20351157,"width":0.04155585,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Constants.php, class checked","depth":8,"bounds":{"left":0.28989363,"top":0.22106944,"width":0.045877658,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ScimProvisioning.php, class checked","depth":8,"bounds":{"left":0.28989363,"top":0.2386273,"width":0.06017287,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Console/Commands 1 file, folder not checked","depth":6,"bounds":{"left":0.27726063,"top":0.25618514,"width":0.06881649,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"DTO/SCIM/AAD 2 files, folder checked","depth":6,"bounds":{"left":0.27726063,"top":0.273743,"width":0.0625,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Request 1 file, folder checked","depth":7,"bounds":{"left":0.2835771,"top":0.29130086,"width":0.044215426,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"CoreUserRequest.php, class checked","depth":8,"bounds":{"left":0.28989363,"top":0.30885875,"width":0.061502658,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Response 1 file, folder checked","depth":7,"bounds":{"left":0.2835771,"top":0.3264166,"width":0.047539894,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"CoreUser.php, class checked","depth":8,"bounds":{"left":0.28989363,"top":0.34397447,"width":0.04454787,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Http/Controllers/API 2 files, folder not checked","depth":6,"bounds":{"left":0.27726063,"top":0.36153233,"width":0.07180851,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Models 2 files, folder not checked","depth":6,"bounds":{"left":0.27726063,"top":0.3790902,"width":0.045212764,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Rules 1 file, folder checked","depth":6,"bounds":{"left":0.27726063,"top":0.39664805,"width":0.03856383,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ListenerRoleCannotHaveAdminOrManagerPermissionRule.php, final class checked","depth":7,"bounds":{"left":0.2835771,"top":0.4142059,"width":0.14261968,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"config 1 file, folder not checked","depth":5,"bounds":{"left":0.27094415,"top":0.43176377,"width":0.040226065,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"tests/Unit 3 files, folder partially checked","depth":5,"bounds":{"left":0.27094415,"top":0.44932163,"width":0.050531916,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Component 2 files, folder partially checked","depth":6,"bounds":{"left":0.27726063,"top":0.4668795,"width":0.05418883,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"AskAnything 1 file, folder not checked","depth":7,"bounds":{"left":0.2835771,"top":0.48443735,"width":0.05319149,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"SCIM/Mutators/Attributes/User 1 file, folder checked","depth":7,"bounds":{"left":0.2835771,"top":0.5019952,"width":0.091090426,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"RoleAttrTest.php, final class checked","depth":8,"bounds":{"left":0.28989363,"top":0.51955307,"width":0.05086436,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Rules 1 file, folder checked","depth":6,"bounds":{"left":0.27726063,"top":0.5371109,"width":0.03856383,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.php, final class checked","depth":7,"bounds":{"left":0.2835771,"top":0.5546688,"width":0.15192819,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":".env.local not checked","depth":5,"bounds":{"left":0.27094415,"top":0.57222664,"width":0.03557181,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"app 13 files, folder partially checked","depth":4,"bounds":{"left":0.27094415,"top":0.11572227,"width":0.040226065,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Component 5 files, folder partially checked","depth":5,"bounds":{"left":0.27726063,"top":0.13328013,"width":0.05418883,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"AskAnything 2 files, folder not checked","depth":6,"bounds":{"left":0.2835771,"top":0.15083799,"width":0.05618351,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"SCIM 3 files, folder checked","depth":6,"bounds":{"left":0.2835771,"top":0.16839585,"width":0.041223403,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mutators/Attributes/User 1 file, folder checked","depth":7,"bounds":{"left":0.28989363,"top":0.1859537,"width":0.0787899,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"RoleAttr.php, class checked","depth":8,"bounds":{"left":0.2962101,"top":0.20351157,"width":0.04155585,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Constants.php, class checked","depth":7,"bounds":{"left":0.28989363,"top":0.22106944,"width":0.045877658,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ScimProvisioning.php, class checked","depth":7,"bounds":{"left":0.28989363,"top":0.2386273,"width":0.06017287,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Console/Commands 1 file, folder not checked","depth":5,"bounds":{"left":0.27726063,"top":0.25618514,"width":0.06881649,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"DTO/SCIM/AAD 2 files, folder checked","depth":5,"bounds":{"left":0.27726063,"top":0.273743,"width":0.0625,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Request 1 file, folder checked","depth":6,"bounds":{"left":0.2835771,"top":0.29130086,"width":0.044215426,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"CoreUserRequest.php, class checked","depth":7,"bounds":{"left":0.28989363,"top":0.30885875,"width":0.061502658,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Response 1 file, folder checked","depth":6,"bounds":{"left":0.2835771,"top":0.3264166,"width":0.047539894,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"CoreUser.php, class checked","depth":7,"bounds":{"left":0.28989363,"top":0.34397447,"width":0.04454787,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Http/Controllers/API 2 files, folder not checked","depth":5,"bounds":{"left":0.27726063,"top":0.36153233,"width":0.07180851,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Models 2 files, folder not checked","depth":5,"bounds":{"left":0.27726063,"top":0.3790902,"width":0.045212764,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Rules 1 file, folder checked","depth":5,"bounds":{"left":0.27726063,"top":0.39664805,"width":0.03856383,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ListenerRoleCannotHaveAdminOrManagerPermissionRule.php, final class checked","depth":6,"bounds":{"left":0.2835771,"top":0.4142059,"width":0.14261968,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Component 5 files, folder partially checked","depth":4,"bounds":{"left":0.27726063,"top":0.13328013,"width":0.05418883,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"AskAnything 2 files, folder not checked","depth":5,"bounds":{"left":0.2835771,"top":0.15083799,"width":0.05618351,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"SCIM 3 files, folder checked","depth":5,"bounds":{"left":0.2835771,"top":0.16839585,"width":0.041223403,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mutators/Attributes/User 1 file, folder checked","depth":6,"bounds":{"left":0.28989363,"top":0.1859537,"width":0.0787899,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"RoleAttr.php, class checked","depth":7,"bounds":{"left":0.2962101,"top":0.20351157,"width":0.04155585,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Constants.php, class checked","depth":6,"bounds":{"left":0.28989363,"top":0.22106944,"width":0.045877658,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ScimProvisioning.php, class checked","depth":6,"bounds":{"left":0.28989363,"top":0.2386273,"width":0.06017287,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"AskAnything 2 files, folder not checked","depth":4,"bounds":{"left":0.2835771,"top":0.15083799,"width":0.05618351,"height":0.017557861},"on_screen":true,"role_description":"text"}]...
|
-8413601905221662012
|
6512249272225642442
|
visual_change
|
accessibility
|
NULL
|
Diff
Changelist:
Changelist:
Changes
Show Diff
Rol Diff
Changelist:
Changelist:
Changes
Show Diff
Rollback...
Refresh
Group By
Expand All
Collapse All
18 files, folder partially checked
app 13 files, folder partially checked
Component 5 files, folder partially checked
AskAnything 2 files, folder not checked
SCIM 3 files, folder checked
Mutators/Attributes/User 1 file, folder checked
RoleAttr.php, class checked
Constants.php, class checked
ScimProvisioning.php, class checked
Console/Commands 1 file, folder not checked
DTO/SCIM/AAD 2 files, folder checked
Request 1 file, folder checked
CoreUserRequest.php, class checked
Response 1 file, folder checked
CoreUser.php, class checked
Http/Controllers/API 2 files, folder not checked
Models 2 files, folder not checked
Rules 1 file, folder checked
ListenerRoleCannotHaveAdminOrManagerPermissionRule.php, final class checked
config 1 file, folder not checked
tests/Unit 3 files, folder partially checked
Component 2 files, folder partially checked
AskAnything 1 file, folder not checked
SCIM/Mutators/Attributes/User 1 file, folder checked
RoleAttrTest.php, final class checked
Rules 1 file, folder checked
ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.php, final class checked
.env.local not checked
app 13 files, folder partially checked
Component 5 files, folder partially checked
AskAnything 2 files, folder not checked
SCIM 3 files, folder checked
Mutators/Attributes/User 1 file, folder checked
RoleAttr.php, class checked
Constants.php, class checked
ScimProvisioning.php, class checked
Console/Commands 1 file, folder not checked
DTO/SCIM/AAD 2 files, folder checked
Request 1 file, folder checked
CoreUserRequest.php, class checked
Response 1 file, folder checked
CoreUser.php, class checked
Http/Controllers/API 2 files, folder not checked
Models 2 files, folder not checked
Rules 1 file, folder checked
ListenerRoleCannotHaveAdminOrManagerPermissionRule.php, final class checked
Component 5 files, folder partially checked
AskAnything 2 files, folder not checked
SCIM 3 files, folder checked
Mutators/Attributes/User 1 file, folder checked
RoleAttr.php, class checked
Constants.php, class checked
ScimProvisioning.php, class checked
AskAnything 2 files, folder not checked...
|
56440
|
NULL
|
NULL
|
NULL
|
|
56443
|
1967
|
37
|
2026-05-19T08:06:32.418300+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177992418_m2.jpg...
|
PhpStorm
|
Shelve Changes
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhostormVIewINavicareCodeLaravelKeractorTOOISrTavs PhostormVIewINavicareCodeLaravelKeractorTOOISrTavsco.s°9 JY-20676-delete-roledeyC) AutomatedReport.onp- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php Xe)-xooricontro||erRateLimit est.onoC) FakeProphetClient.ohv> _ Midd eware40) SoftPhoneManager.phpRequests() ListenerRoleCannotHaveAdmInteractionsInvitationsListenerRoleCannotHaveAdminOrManagerPermissionRIHlobsListeners© SyncActivity.php© Crm/Close/Service.phpD Mcpm Modelsfinal class SavedSearchCRUDFeaturet194 D >public function userCanUpdateASM NotificationsD OrganizationSettingsD PlaylistsD Policies( Repositories( RulesC SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search257 D ># Phrun1c rramework Accrabucespublic function userCanDeleteAS314›_ serviceProvidersLocal ChandesConsole XLooXv Changes 18 files=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnythingc) AsKAnvihinaPromotbto.ono apo/comoonent/AskAnvihino/Dros© AskAnvthinaPromptService.php app/Component/AskAnvthingC)AskAnvthinaPromotServiceTlest.oho tests/Unit/Comoonent/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/APIV2C) Constants ono aoo/Como.ent/SCIMI(C) Coreuser.oho aoo/DTO/SCIMIAAD/ResoonseC) CoreUserRequest.ono ano/DTO/SCIMIAAD/RequestiC).liminnvDebuacommand.nhn ann/console/CommandsC) ListenerRoleCannotHlaveAdminOrManagerPermissionRule.ohn aon/Rulesi@ ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Unit/Fphp loadina.nho confial© RoleAttr.php app/Component/SCIM/Mutators/Attributes/Usec) RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/Useri© ScimProvisioning.php app/Component/SCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt apdTraw sal qauerv.sal app© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK FILTERING_IMPLEMENTATION.md apd© AskAnythingPrompt.phpAsKAnywingPromptuto.pnp© BaseService.phpVa Mutators/Attributes/User 1 fileV © RoleAttr.phpv © Constants.phpV © ScimProvisioning.php4 added 4 modifiedCommit MessageScim provisioning with riolesv DiftJG¢→Side-by-side viewerDo notignoreHighlight wordsculrent version apocon8 5604af40 app/Cdeclare strict typess):use Jiminny Modnamespace Jiminny Comoonent SCIM Mutators Attributes User:use liminnv Moruse Jiminny Mocuse liminnv Seruse Illuminate\Support \Facades \Validator;use Tlluminate Sumnort Facades Loo:use Sentry:use Jiminny \Component\Acl\RoleChangeContext;use Jiminnv Comnonent Acl RoleChangeLodger:class ScimProviuse Jiminnv Conpublic funcorivace readonly userservice suserserviceprivate readonly RoleChangeLogger SroleChangeLoggerpublic function validateUseridinput($id, Team Steam): bool['email' => $dto->getEmailPrimaryWork)],SuserUodateDatalif (! SnewUser->roles()->exists()) {Snewliser->addRole User: ROLE ANALYSTO:/** @var Role Srole */Snole = Role• •quenvo->whenedr'namel => Isen: •ROI F ANAI VSTID->finctinCailo•= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~Shelve ChanaesChangelist:erycollectiom...• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:32CascadeAsk Jiminny Report M+0 ..3. loggle validationrtsController.php: 126-169 - In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alliAsk anvthina (4D14 @s Codo Chudo Onuc 17 Modium•01.4 difterencesCancelShelve Changesix = null): array{...}Current versionuse Jiminny Models Role;use liminnv Model c Teamuse Jiminny Models\User;luse liminnv Senvices IlcenSenvico•use Jiminny\Contracts\Acl \RoleRepositoryInterface:use Illuminate\Support\Facades \Validator:use Jiminny kuLes uependenckoleskule.use Jiminny Rules\ListenerRoleCannotHaveAdmin0rManagerPermissionRule:use Jiminny Rules \ListenerRoleRequiresListenerFeatureRuleuse Jiminny Actions UpdateUserRolesAction:use Jiminny DTO\Roles UserRolesSyncDT0:use Sentry:class Sc1mProv1s10n1nqlpublic function -_constructorivate readonly Daspatcher seventiisoatcher.private readonly UserService $userService,orivate readonly RolechangeLogger SroleChangeLogger..private readonly RoleRepositoryInterface $roleRepository,orivate readoniv UodatelserRolesAction SundatelserRolesAction.nublic function validatellsenTdinnut(Sid. Team Steam• hoollW Windsurf Teams214-1UTE.RIPo. 4 spaces...
|
NULL
|
-2477464062535398624
|
NULL
|
click
|
ocr
|
NULL
|
PhostormVIewINavicareCodeLaravelKeractorTOOISrTavs PhostormVIewINavicareCodeLaravelKeractorTOOISrTavsco.s°9 JY-20676-delete-roledeyC) AutomatedReport.onp- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php Xe)-xooricontro||erRateLimit est.onoC) FakeProphetClient.ohv> _ Midd eware40) SoftPhoneManager.phpRequests() ListenerRoleCannotHaveAdmInteractionsInvitationsListenerRoleCannotHaveAdminOrManagerPermissionRIHlobsListeners© SyncActivity.php© Crm/Close/Service.phpD Mcpm Modelsfinal class SavedSearchCRUDFeaturet194 D >public function userCanUpdateASM NotificationsD OrganizationSettingsD PlaylistsD Policies( Repositories( RulesC SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search257 D ># Phrun1c rramework Accrabucespublic function userCanDeleteAS314›_ serviceProvidersLocal ChandesConsole XLooXv Changes 18 files=.env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnythingc) AsKAnvihinaPromotbto.ono apo/comoonent/AskAnvihino/Dros© AskAnvthinaPromptService.php app/Component/AskAnvthingC)AskAnvthinaPromotServiceTlest.oho tests/Unit/Comoonent/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/APIV2C) Constants ono aoo/Como.ent/SCIMI(C) Coreuser.oho aoo/DTO/SCIMIAAD/ResoonseC) CoreUserRequest.ono ano/DTO/SCIMIAAD/RequestiC).liminnvDebuacommand.nhn ann/console/CommandsC) ListenerRoleCannotHlaveAdminOrManagerPermissionRule.ohn aon/Rulesi@ ListenerRoleCannotHaveAdminOrManagerPermissionRuleTest.ohn tests/Unit/Fphp loadina.nho confial© RoleAttr.php app/Component/SCIM/Mutators/Attributes/Usec) RoleAttrTest.nhn tests/Unit/Comnonent/SCIM/Mutators/Attributes/Useri© ScimProvisioning.php app/Component/SCIM© Search.php app/Models/ActivityUnversioned Files 9 filesE.env.nikilocal app=.env.other app© CanAccessAiReportsTest.php tests/Unit/Policies© CreateMockAskJiminnyReportResultCommand.php app/Console/Commands/RE favicon.ico publicEids.txt apdTraw sal qauerv.sal app© SimulateWebhooksCommand.php app/Console/Commands/Crm/HubspotM+ WEBHOOK FILTERING_IMPLEMENTATION.md apd© AskAnythingPrompt.phpAsKAnywingPromptuto.pnp© BaseService.phpVa Mutators/Attributes/User 1 fileV © RoleAttr.phpv © Constants.phpV © ScimProvisioning.php4 added 4 modifiedCommit MessageScim provisioning with riolesv DiftJG¢→Side-by-side viewerDo notignoreHighlight wordsculrent version apocon8 5604af40 app/Cdeclare strict typess):use Jiminny Modnamespace Jiminny Comoonent SCIM Mutators Attributes User:use liminnv Moruse Jiminny Mocuse liminnv Seruse Illuminate\Support \Facades \Validator;use Tlluminate Sumnort Facades Loo:use Sentry:use Jiminny \Component\Acl\RoleChangeContext;use Jiminnv Comnonent Acl RoleChangeLodger:class ScimProviuse Jiminnv Conpublic funcorivace readonly userservice suserserviceprivate readonly RoleChangeLogger SroleChangeLoggerpublic function validateUseridinput($id, Team Steam): bool['email' => $dto->getEmailPrimaryWork)],SuserUodateDatalif (! SnewUser->roles()->exists()) {Snewliser->addRole User: ROLE ANALYSTO:/** @var Role Srole */Snole = Role• •quenvo->whenedr'namel => Isen: •ROI F ANAI VSTID->finctinCailo•= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~Shelve ChanaesChangelist:erycollectiom...• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:32CascadeAsk Jiminny Report M+0 ..3. loggle validationrtsController.php: 126-169 - In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alliAsk anvthina (4D14 @s Codo Chudo Onuc 17 Modium•01.4 difterencesCancelShelve Changesix = null): array{...}Current versionuse Jiminny Models Role;use liminnv Model c Teamuse Jiminny Models\User;luse liminnv Senvices IlcenSenvico•use Jiminny\Contracts\Acl \RoleRepositoryInterface:use Illuminate\Support\Facades \Validator:use Jiminny kuLes uependenckoleskule.use Jiminny Rules\ListenerRoleCannotHaveAdmin0rManagerPermissionRule:use Jiminny Rules \ListenerRoleRequiresListenerFeatureRuleuse Jiminny Actions UpdateUserRolesAction:use Jiminny DTO\Roles UserRolesSyncDT0:use Sentry:class Sc1mProv1s10n1nqlpublic function -_constructorivate readonly Daspatcher seventiisoatcher.private readonly UserService $userService,orivate readonly RolechangeLogger SroleChangeLogger..private readonly RoleRepositoryInterface $roleRepository,orivate readoniv UodatelserRolesAction SundatelserRolesAction.nublic function validatellsenTdinnut(Sid. Team Steam• hoollW Windsurf Teams214-1UTE.RIPo. 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56442
|
1966
|
27
|
2026-05-19T08:06:32.420623+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177992420_m1.jpg...
|
PhpStorm
|
Shelve Changes
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:32QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4Message #the_people_of_jiminny+...
|
NULL
|
2982936479853032123
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:32QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4Message #the_people_of_jiminny+...
|
56438
|
NULL
|
NULL
|
NULL
|
|
56444
|
1966
|
28
|
2026-05-19T08:06:35.786634+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177995786_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% <7Tue 19 May 11:06:35QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4637Message #the_people_of_jiminny+...
|
NULL
|
-301870021424380514
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% <7Tue 19 May 11:06:35QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 4637Message #the_people_of_jiminny+...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56445
|
1967
|
38
|
2026-05-19T08:06:36.174245+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177996174_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.19952115,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.19952115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.19792499,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
7900466997463401669
|
-5826444973847630902
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
PhostormViewINavicareCodeKeractorTOOISWindowFV faVsco.js°9 JY-20676-delete-report-related-objectsProiectC) AutomatedReport.onp© AskAnythingPromptServiceTest.php- ActivtvaskAnvihind est.ono© SavedSearchCRUDFeatureTest.php Xe) -xooricontro||erRateLimit est.onoAsKAnywingPromptuto.pnpC) FakeProphetClient.ohv© BaseService.php> _ Midd ewareC SoftPhoneManager.phpgscimProvisioning.phpRequestsAcuivily/close/service.ohol Interactionsa Invitations(C) TextMessaqingService.phgIHlobsfinal class SavedSearchCRUDFeatureTest extends TestcaseщЛ2A16 A VIn ListenersD McpN Modelsi194 D >#[\PHPUnit\Framework\Attributes\Test]public function userCanUpdateASavedSearchBasedOnActivityFilters: void{...}M Notificationsm oraanizationsettingsD PlaylistsD Policies( RepositoriesC RulesC SavedSearches@ SavedSearchCRUDFeatureTest.php› C Search257 D >#[\PHPUnit\Framework\Attributes\Test]public function userCanDeleteASavedSearch: void{...}_ serviceProvidersLocal ChandesConsole XLooXHighlight words x 15 ?Scim orovisionina with rioles 8 files. Mom.&Base version app/Component/SCIM/Constants.php> CrmOwnerResolver 2 files. A minute aad> JY-20891 SMS Text relav EU 3 files. 15.05.26. 14:05.> JD & SendRenort.Job 2 files. 13.05.26. 12•38> reorder calls 1 file. 11.05.26. 10:09Move non naainator coarch callc to client-scoarch 1 file 11.05 26 . 10-07• Almast readv one call to he tected & filec 8 05 26 14-54> hubsnot rate limit temn checkout 17 filec 8 05 26 11-49public const META_ID = 'id':public const META_PHONE_NUMBERS = 'phoneNumbers' :public const META TITLE = 'title':public const META PATH = 'path':public const META ENTERPRISE SCHEMA = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User':> caved coarch delete 1 file 27 04 26 14-59public const META DEPARTMENT = "department'*public const META_META = 'meta';› expiration message 6 files, 27.04.26, 9:23• 1Ip dev loac 1 file 2404 26 12.021› tem test 1 file, 24.04.26, 10:36)ucor trancfarmor 2 filoc 2204 06 15012public const USER PATCH ATTR PRIMARY EMAIL = 'emailsitvpe ea "work"].value'•ouounc const USER PATCHATIR SECONDARY EMAIL ='emalis tvoe ed "home",value',> email ready 9 files, 23.04.26, 15:31> Email on not sent 5 files. 21.04.26, 19:38> Planhat track interest event 2 files. 21.04.26. 13:56> UP tracking controller 1 file. 20.04.26, 9:22> Don't send if no s3 path (fix update to failed) 1 file. 17.04.26. 12:56> FEATURE CHANGES 3 files. 6.04.26. 13:40oublic const USER PATCH ATTR PHONE NUMBER = "ohoneNumbers tvoe ea "work" value':nublic constUSER_PATCH_ATTR_PHONE_NUMBER_MOBILE = 'phoneNumbers[type eq "mobile"].value';oublic const USER SUPPORTED PATCH ATTRIBUTES MUTATORS =self::USER_PATCH_ATTR_TITLE => Mutators\Attributes\User\TitleAttr::class,Se+.•USER PATCHATTR ACTTVE= Mutatons Attrihutes Uisen ActiveAttn:.cllass.web,oho tix router 1 tile, 1.04.26, 9:23|> SF Tvpe error fix 2 files. 31.03.26. 12:26> next automated report task 1 file. 31.03. 26. 10:55)• who knows 2 files. 24.03, 26. 14:45> temo fix 32 files. 24.03.26. 10:51lself:-USER PATCH ATTR PRIMARY EMATI => Mutatons Attrihutes Isen PnimanvEmailAttn:classlself::USER_PATCH_ATTR_SECONDARY_EMAIL => Mutators\Attributes\User\SecondaryEmailAttr::class,solf.-ISER PATCH ATTR PHONE NUMRER => Mutatons Attnihutes Ilsen PhoneNumhenPnimanvAttn.•classlself::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE => Mutators\Attributes\User\PhoneNumberSecondaryAttr::class.env local not sure why it was chanded 1 file. 24.03.26. 10:04> Al Renorts 21 files. 19.03.26. 18:07> ORJECT WERHOOK PROCESSING 5 files. 5.03.26. 15:22public const FILTER_OPERATOR_EQ = 'eq';• OR.ISCT RATCH CYNC 12 fllec 5 02 26 15:21The Hunsnell nluain hac heon denrecated. If vou're not writing in Hungarian vou can cafolv uninctall HuncnelliJanquades (todav 10-00)• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:35AskJiminnyReportActivityServiceTest v= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyCascadeA console [STAGING]© CoachingFeedbackCoachUserln.php XAsk Jiminny Report M+0 ..final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini mmocd → null, "status → Talsel3. loggle validation29 6tpublic function shouldApplyQueries: bool{...}rtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. Tests34 6tpublic function getQueries: FilterDefinitionQueryCollection{...}45 6touolic function toArravo: arrav...?AskAnythingPromptServiceTest.php — Updated two existing update() mock expectations to match the new payload (['ask_anything_prompt_id' = null, 'status' = falsel ).Per your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.1 usage=118private function getOptions: arrayt...public function getValue: arrayt...usage8 files 400-7 )Reiect allAccent alliprivate function getDefaultValue: arrayt...135136 >Ask anvthina (*4D1public function getValidationRules(?string $prefix = null): array{...}+ <> Code Claude Opus 4.7 Medium•01.3 ditterencesa Shelved versionpublic const META_ID = 'id';public const META_PHONE_NUMBERS = 'phoneNumbers':public const META TITLE = 'title':Ist META ROLES = 'roles' :public const META PATH = 'path':public const META ENTERPRISE SCHEMA = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User':public const META DEPARTMENT = 'department':public const META META = "meta'"ouounc const USER PATCh ATIR PRIMARY EMAILE'emaris tvoe ed "work"', value',public const USER PATCH ATTR SECONDARY EMAIL = 'emailsityne eo "home"].value'•nublic const USER PATCH ATTR PHONE NUMBER = 'ohoneNumbers tvoe ea "work"] value':public const USER_PATCH_ATTR_PHONE_NUMBER_MOBILE = 'phoneNumbers[type eq "mobile"].value':publicUSER PATCH ATTR ROLES = 'rolesnuhiie cons+ USER SUPPORTED PATCH ATTRIRUTES MUTATORS =self::USER_PATCH_ATTR_TITLE => Mutators|Attributes\User\TitleAttr: :class,self:-ISER PATCH ATTR ACTTVE => Mutatons Attrihutesllsen ActiveAttn.-class.solf.-ISER PATCH ATTR PRTMARV EMATI => Mutatons Attnihutes Iisen PnimanvEmailAttn.class.self::USER_PATCH_ATTR_SECONDARY_EMAIL => Mutators\Attributes\User\SecondaryEmailAttr::class,solf.-lSER pATcH ATTR PHONE NUMRER => Mutatonc Attrihutes Ilsen PhoneNumhenPnimanvAttn.•class.self::USER_PATCH_ATTR_PHONE_NUMBER_MOBILE => Mutators\Attributes\User\PhoneNumberSecondaryAttr::class,self::USER_PATCH_ATTR_ROLES => Mutators\Attributes\User\RoleAttr::class,WN Windsurf Teams214-1UTC.81io 4 spaces...
|
56443
|
NULL
|
NULL
|
NULL
|
|
56447
|
1967
|
39
|
2026-05-19T08:06:39.726314+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177999726_m2.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.390625,"top":0.19952115,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"bounds":{"left":0.4005984,"top":0.19952115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.4119016,"top":0.19792499,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.4192154,"top":0.19792499,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"bounds":{"left":0.15990691,"top":0.0,"width":0.2662899,"height":0.49162012},"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56446
|
1966
|
29
|
2026-05-19T08:06:39.794123+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779177999794_m1.jpg...
|
PhpStorm
|
faVsco.js – SavedSearchCRUDFeatureTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"16","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Tests\\Feature\\SavedSearches;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Illuminate\\Support\\Str;\nuse Mockery\\MockInterface;\nuse Illuminate\\Database\\Eloquent\\Factories\\Sequence;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Testing\\Fluent\\AssertableJson;\nuse Jiminny\\Events\\Nudges\\NudgeCreated;\nuse Jiminny\\Models\\Activity\\Search;\nuse Jiminny\\Models\\Activity\\SearchFilter;\nuse Jiminny\\Models\\Nudge;\nuse Jiminny\\Models\\Role;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\ElasticActivityRepository;\nuse Tests\\TestCase;\n\nfinal class SavedSearchCRUDFeatureTest extends TestCase\n{\n use DatabaseTransactions;\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanGetAListOfSavedSearches(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'status' => User::STATUS_ACTIVE,\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create();\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n $nudges = Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->getJson(route('api.saved_search.index'))\n ->assertStatus(200)\n ->assertJson(\n fn (AssertableJson $json) =>\n $json->has(1)\n ->first(\n fn ($json) =>\n $json->where('id', $search->id_string)\n ->where('name', $search->getName())\n ->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])\n ->has('nudges', 2)\n ->has(\n 'nudges.0',\n fn ($json) =>\n $json->where('id', $nudges[0]->id_string)\n ->where('frequency', 'daily')\n ->where('channel', 'email')\n ->has('expiresAt')\n )\n ->has(\n 'nudges.1',\n fn ($json) =>\n $json->where('id', $nudges[1]->id_string)\n ->where('frequency', 'weekly')\n ->where('channel', 'slack')\n ->has('expiresAt')\n )\n )\n );\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanCreateASavedSearchBasedOnActivityFilters(): void\n {\n $this->markTestSkipped('Needs to be fixed');\n\n Event::fake();\n\n $this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {\n $mock->shouldReceive('onDemandScroll')\n ->times(2)\n ->andReturn(LazyCollection::empty());\n });\n\n /** @var Team $team */\n $team = Team::factory()->create([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1, // temporary\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->createQuietly([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->postJson(route('api.saved_search.create'), [\n 'name' => '::searchName::',\n 'filters' => [\n 'min_duration' => 1,\n 'only_recorded' => 1,\n ],\n 'nudges' => [\n [\n 'frequency' => 'daily',\n 'channel' => 'email',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n [\n 'frequency' => 'daily',\n 'channel' => 'slack',\n 'expiresAt' => now()->addWeek()->format('Y-m-d'),\n ],\n ],\n ])\n ->assertStatus(200);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => '::searchName::',\n 'user_id' => $user->id,\n ]);\n\n $search = $user->searches()->first();\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 2,\n ]);\n\n $this->assertDatabaseHas('nudges', [\n 'activity_search_id' => $search->id,\n 'frequency' => 2,\n 'channel' => 4,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'min_duration',\n 'value' => 1,\n ]);\n\n $this->assertDatabaseHas('activity_search_filters', [\n 'activity_search_id' => $search->id,\n 'filter' => 'only_recorded',\n 'value' => 1,\n ]);\n\n Event::assertDispatched(NudgeCreated::class, 2);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanUpdateASavedSearchBasedOnActivityFilters(): void\n {\n /** @var Team $team */\n $team = Team::factory()->createQuietly([\n 'uuid' => Str::uuid()->toString(),\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->putJson(route('api.saved_search.update', $search->id_string), [\n 'name' => 'Updated Search Name',\n ])->assertOk()\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'name' => 'Search Name',\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseHas('activity_searches', [\n 'name' => 'Updated Search Name',\n 'user_id' => $user->id,\n ]);\n }\n\n #[\\PHPUnit\\Framework\\Attributes\\Test]\n public function userCanDeleteASavedSearch(): void\n {\n /** @var Team $team */\n $team = Team::factory()->create([\n 'crm_id' => 1,\n ]);\n\n $adminRole = Role::firstWhere('name', User::ROLE_ADMIN);\n\n /** @var User $user */\n $user = User::factory()\n ->hasAttached($adminRole, ['user_type' => 'user'])\n ->create([\n 'name' => '::userName::',\n 'team_id' => $team->id,\n ]);\n\n $team->owner_id = $user->id;\n $team->save();\n\n $search = Search::factory()->for($user)->create([\n 'name' => 'Search Name',\n ]);\n\n SearchFilter::factory()\n ->for($search)\n ->count(2)\n ->state(new Sequence(\n ['filter' => 'min_engaging_questions', 'value' => 3],\n ['filter' => 'max_customer_questions', 'value' => 5],\n ))->create();\n\n Nudge::factory()\n ->count(2)\n ->state(\n new Sequence(\n ['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],\n ['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],\n )\n )\n ->create(['activity_search_id' => $search->id]);\n\n $this->apiGuardLogin($user);\n\n $this->actingAs($user)\n ->deleteJson(route('api.saved_search.delete', $search->id_string))\n ->assertStatus(200)\n ->assertJson([]);\n\n $this->assertDatabaseMissing('activity_searches', [\n 'user_id' => $user->id,\n ]);\n\n $this->assertDatabaseMissing('activity_search_filters', [\n 'activity_search_id' => $search->id,\n ]);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6509625738266471330
|
-8996616125002602716
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
3
16
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Tests\Feature\SavedSearches;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Str;
use Mockery\MockInterface;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event;
use Illuminate\Testing\Fluent\AssertableJson;
use Jiminny\Events\Nudges\NudgeCreated;
use Jiminny\Models\Activity\Search;
use Jiminny\Models\Activity\SearchFilter;
use Jiminny\Models\Nudge;
use Jiminny\Models\Role;
use Jiminny\Models\Team;
use Jiminny\Models\User;
use Jiminny\Repositories\ElasticActivityRepository;
use Tests\TestCase;
final class SavedSearchCRUDFeatureTest extends TestCase
{
use DatabaseTransactions;
#[\PHPUnit\Framework\Attributes\Test]
public function userCanGetAListOfSavedSearches(): void
{
$this->markTestSkipped('Needs to be fixed');
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'status' => User::STATUS_ACTIVE,
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create();
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
$nudges = Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->getJson(route('api.saved_search.index'))
->assertStatus(200)
->assertJson(
fn (AssertableJson $json) =>
$json->has(1)
->first(
fn ($json) =>
$json->where('id', $search->id_string)
->where('name', $search->getName())
->where('filters', ['max_customer_questions' => 5, 'min_engaging_questions' => 3])
->has('nudges', 2)
->has(
'nudges.0',
fn ($json) =>
$json->where('id', $nudges[0]->id_string)
->where('frequency', 'daily')
->where('channel', 'email')
->has('expiresAt')
)
->has(
'nudges.1',
fn ($json) =>
$json->where('id', $nudges[1]->id_string)
->where('frequency', 'weekly')
->where('channel', 'slack')
->has('expiresAt')
)
)
);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanCreateASavedSearchBasedOnActivityFilters(): void
{
$this->markTestSkipped('Needs to be fixed');
Event::fake();
$this->partialMock(ElasticActivityRepository::class, function (MockInterface $mock) {
$mock->shouldReceive('onDemandScroll')
->times(2)
->andReturn(LazyCollection::empty());
});
/** @var Team $team */
$team = Team::factory()->create([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1, // temporary
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->createQuietly([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$this->apiGuardLogin($user);
$this->actingAs($user)
->postJson(route('api.saved_search.create'), [
'name' => '::searchName::',
'filters' => [
'min_duration' => 1,
'only_recorded' => 1,
],
'nudges' => [
[
'frequency' => 'daily',
'channel' => 'email',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
[
'frequency' => 'daily',
'channel' => 'slack',
'expiresAt' => now()->addWeek()->format('Y-m-d'),
],
],
])
->assertStatus(200);
$this->assertDatabaseHas('activity_searches', [
'name' => '::searchName::',
'user_id' => $user->id,
]);
$search = $user->searches()->first();
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 2,
]);
$this->assertDatabaseHas('nudges', [
'activity_search_id' => $search->id,
'frequency' => 2,
'channel' => 4,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'min_duration',
'value' => 1,
]);
$this->assertDatabaseHas('activity_search_filters', [
'activity_search_id' => $search->id,
'filter' => 'only_recorded',
'value' => 1,
]);
Event::assertDispatched(NudgeCreated::class, 2);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanUpdateASavedSearchBasedOnActivityFilters(): void
{
/** @var Team $team */
$team = Team::factory()->createQuietly([
'uuid' => Str::uuid()->toString(),
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->putJson(route('api.saved_search.update', $search->id_string), [
'name' => 'Updated Search Name',
])->assertOk()
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'name' => 'Search Name',
'user_id' => $user->id,
]);
$this->assertDatabaseHas('activity_searches', [
'name' => 'Updated Search Name',
'user_id' => $user->id,
]);
}
#[\PHPUnit\Framework\Attributes\Test]
public function userCanDeleteASavedSearch(): void
{
/** @var Team $team */
$team = Team::factory()->create([
'crm_id' => 1,
]);
$adminRole = Role::firstWhere('name', User::ROLE_ADMIN);
/** @var User $user */
$user = User::factory()
->hasAttached($adminRole, ['user_type' => 'user'])
->create([
'name' => '::userName::',
'team_id' => $team->id,
]);
$team->owner_id = $user->id;
$team->save();
$search = Search::factory()->for($user)->create([
'name' => 'Search Name',
]);
SearchFilter::factory()
->for($search)
->count(2)
->state(new Sequence(
['filter' => 'min_engaging_questions', 'value' => 3],
['filter' => 'max_customer_questions', 'value' => 5],
))->create();
Nudge::factory()
->count(2)
->state(
new Sequence(
['frequency' => 2, 'channel' => 2, 'expires_at' => now()->addWeek()],
['frequency' => 4, 'channel' => 4, 'expires_at' => now()->addMonth()],
)
)
->create(['activity_search_id' => $search->id]);
$this->apiGuardLogin($user);
$this->actingAs($user)
->deleteJson(route('api.saved_search.delete', $search->id_string))
->assertStatus(200)
->assertJson([]);
$this->assertDatabaseMissing('activity_searches', [
'user_id' => $user->id,
]);
$this->assertDatabaseMissing('activity_search_filters', [
'activity_search_id' => $search->id,
]);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
56444
|
NULL
|
NULL
|
NULL
|
|
56448
|
1966
|
30
|
2026-05-19T08:06:41.011290+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178001011_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"}]...
|
4534541704019487986
|
-8697414396099768401
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56449
|
1967
|
40
|
2026-05-19T08:06:41.023217+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178001023_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-9180173071703886651
|
-8697414396099768401
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide...
|
56447
|
NULL
|
NULL
|
NULL
|
|
56450
|
1967
|
41
|
2026-05-19T08:06:42.780890+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178002780_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4508527917909716569
|
-8683903597217656915
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56452
|
1967
|
42
|
2026-05-19T08:06:46.859388+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178006859_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
4868266520269905854
|
-8697414396099768401
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification...
|
56450
|
NULL
|
NULL
|
NULL
|
|
56451
|
1966
|
31
|
2026-05-19T08:06:46.874295+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178006874_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7601088069291092266
|
-8698540296006611025
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}...
|
56448
|
NULL
|
NULL
|
NULL
|
|
56453
|
1967
|
43
|
2026-05-19T08:06:48.831553+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178008831_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
iilPhostormProiectViewINavicareCodeLaravelKeractor iilPhostormProiectViewINavicareCodeLaravelKeractorTOOISFV faVsco.js?9 JY-20676-delete-report-related-objectsC) AutomatedReport.onp(c) Search.onp= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyTeamRetentionPolicyFeatureTest.php" ThemeTopicUpdateFeatureTest.phpUserOnboardFeatureTest.php› Intearation0) Services?DStuosv M Unit> Actions• Component> ActionltemsActivitv› ActivityAnalyticsM ActivitvSearchAiActivityTypeTM AiAutomationD AiCallScoring• M AskAnything©) AskAnythingPromptServiceTest.phpch HistorvServicelest.ong)M Ack liminnyAil© AskAnythingPrompt.phpC) ActivityController.onpA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~© ScimProvisioning.php© SyncActivity.phpccrm/close/service.oho29 6tpublic function shouldApplyQueries(): boolf...}class ASKAnyth1ngPromptServ1celest extends TestcasepubLICtunction testlelete.skanvthinopromoto: vozd34 6t >public function getQueries: FilterDefinitionQueryCollection{...}nes."updace)45 6touolic function toArravo: arrav...->once->with(['ask_anything_prompt_id' => null]);Accept Reiect1 usage->with(['ask_anything_prompt_id' => null, 'status' => falsel);118private function getOptions: arrayt...Soromot->exoects(sthis->onceOblpublic function getValue: arrayt...->methoda constraint:'automatedRenorts')130332->wil Return(SrelationMocka:lusage8 files 400-7 )334$user = $this->createMockosusen-seyrectef2.edits.ton/ v Accept File &X Reiect File 42g+ 7 of 7 files →131 |_135_136 С >private function getDefaultValue: arrayt...Ask anvthina (4D1public function getValidationRules(?string $prefix = null): array{...}+ <> Code Claude Opus 4.7 Medium->methodd constraint: "aettd")Local ChandesConsoleLooXChanges 10 tlles=.env.local appActivityController.php app/Http/Controllers/APl© AskAnythingPrompt.php app/Models/AskAnything© AskAnvthinaPromptDto.php app/Component/AskAnvthina/Dtos© AskAnvthinaPromptService.php app/Component/AskAnvthing@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2Side-by-side viewerDo not ignoreHighlight words"X Bà ộ?5604af40 app/Http/Controllers/API/ActivityController.phpCurrent versionpublic function deleteActivitySearch(Request Srequest, Search $search): JsonResponsepublic function deleteActivitySearch(Request Srequest, Search $search): JsonResponseSthis-sauthonize("deletel Scpanch)-Sthis-sauthonize("deletel Sceanch)// Orpan any AutomatedReports that use this searciC) JiminnvDebuaCommand.oho ao/Console/Commands.Ssearch->automatedReports->withTrashed->update(['activity_search_id' => null]):php logging.php configC) Search.nhn anr/Models/Activitv// Delete filters and the search itself• Unversioned Files 9 filesissearch-rilters->delete=env.nikilocal annE .env.other appc) CanAccessAiRenortsTest.oho tests/Unit/Policie.// Disable andany AutomatedReports that use this searchSsearch->automatedReports->withTrashed->update(['activity_search_id' => null,letatuci = folco/I Delete filters and the search itselfSsearch->filters->deleteO:(C) CreateMockAsk.liminnvRenortResultCommand.ohn ann/Console/Commands/RSsearch->deleteoe favicon.ico nublic= ide tut andTraw_sqL_query.sql app@ SimulateWebhooksCommand.php app/Console/Commands/Crm/HubsporM4 WEBHOOK_FILTERING_IMPLEMENTATION.md app• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:48AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report M+0 ..mocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alli•01.1ditterenceThe Huncnell nluain hac họ.aries for other lanquades (todav 10-00)WN Windsurf Toams 228-1 UTF.8io 4 spaces...
|
NULL
|
1853126091276320699
|
NULL
|
visual_change
|
ocr
|
NULL
|
iilPhostormProiectViewINavicareCodeLaravelKeractor iilPhostormProiectViewINavicareCodeLaravelKeractorTOOISFV faVsco.js?9 JY-20676-delete-report-related-objectsC) AutomatedReport.onp(c) Search.onp= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyTeamRetentionPolicyFeatureTest.php" ThemeTopicUpdateFeatureTest.phpUserOnboardFeatureTest.php› Intearation0) Services?DStuosv M Unit> Actions• Component> ActionltemsActivitv› ActivityAnalyticsM ActivitvSearchAiActivityTypeTM AiAutomationD AiCallScoring• M AskAnything©) AskAnythingPromptServiceTest.phpch HistorvServicelest.ong)M Ack liminnyAil© AskAnythingPrompt.phpC) ActivityController.onpA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~© ScimProvisioning.php© SyncActivity.phpccrm/close/service.oho29 6tpublic function shouldApplyQueries(): boolf...}class ASKAnyth1ngPromptServ1celest extends TestcasepubLICtunction testlelete.skanvthinopromoto: vozd34 6t >public function getQueries: FilterDefinitionQueryCollection{...}nes."updace)45 6touolic function toArravo: arrav...->once->with(['ask_anything_prompt_id' => null]);Accept Reiect1 usage->with(['ask_anything_prompt_id' => null, 'status' => falsel);118private function getOptions: arrayt...Soromot->exoects(sthis->onceOblpublic function getValue: arrayt...->methoda constraint:'automatedRenorts')130332->wil Return(SrelationMocka:lusage8 files 400-7 )334$user = $this->createMockosusen-seyrectef2.edits.ton/ v Accept File &X Reiect File 42g+ 7 of 7 files →131 |_135_136 С >private function getDefaultValue: arrayt...Ask anvthina (4D1public function getValidationRules(?string $prefix = null): array{...}+ <> Code Claude Opus 4.7 Medium->methodd constraint: "aettd")Local ChandesConsoleLooXChanges 10 tlles=.env.local appActivityController.php app/Http/Controllers/APl© AskAnythingPrompt.php app/Models/AskAnything© AskAnvthinaPromptDto.php app/Component/AskAnvthina/Dtos© AskAnvthinaPromptService.php app/Component/AskAnvthing@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2Side-by-side viewerDo not ignoreHighlight words"X Bà ộ?5604af40 app/Http/Controllers/API/ActivityController.phpCurrent versionpublic function deleteActivitySearch(Request Srequest, Search $search): JsonResponsepublic function deleteActivitySearch(Request Srequest, Search $search): JsonResponseSthis-sauthonize("deletel Scpanch)-Sthis-sauthonize("deletel Sceanch)// Orpan any AutomatedReports that use this searciC) JiminnvDebuaCommand.oho ao/Console/Commands.Ssearch->automatedReports->withTrashed->update(['activity_search_id' => null]):php logging.php configC) Search.nhn anr/Models/Activitv// Delete filters and the search itself• Unversioned Files 9 filesissearch-rilters->delete=env.nikilocal annE .env.other appc) CanAccessAiRenortsTest.oho tests/Unit/Policie.// Disable andany AutomatedReports that use this searchSsearch->automatedReports->withTrashed->update(['activity_search_id' => null,letatuci = folco/I Delete filters and the search itselfSsearch->filters->deleteO:(C) CreateMockAsk.liminnvRenortResultCommand.ohn ann/Console/Commands/RSsearch->deleteoe favicon.ico nublic= ide tut andTraw_sqL_query.sql app@ SimulateWebhooksCommand.php app/Console/Commands/Crm/HubsporM4 WEBHOOK_FILTERING_IMPLEMENTATION.md app• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:48AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report M+0 ..mocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent alli•01.1ditterenceThe Huncnell nluain hac họ.aries for other lanquades (todav 10-00)WN Windsurf Toams 228-1 UTF.8io 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56454
|
1966
|
32
|
2026-05-19T08:06:50.427610+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178010427_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:49QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 42Message #the_people_of_jiminny+...
|
NULL
|
-1178307193682157525
|
NULL
|
click
|
ocr
|
NULL
|
SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1D SlackFileEditViewGoHistoryWindowHelpAPPDOCKER• ₴1DEV (-zsh)₴82app/Jobs/Crm/MatchActivityCrmData.phpapp/Jobs/Middleware/HandleHubspotRateLimit.phpAPP (-zst47++++++p42++++++*app/Mcp/Servers/JiminnyServer.phpapp/Mcp/Tools/GetMeTool.php157++++++•app/Models/Feature/FeatureEnum.phpapp/Services/Activity/HubSpot/ProviderResolver.php+-app/Services/Activity/HubSpot/ProviderResolverInterface.phpapp/Services/Activity/HubSpot/Providers/Provider.phpapp/Services/Activity/HubSpot/Providers/ProviderKixie.php+-app/Services/Activity/HubSpot/Providers/Provider0rum.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilio.phpapp/Services/Activity/HubSpot/Providers/ProviderTwilioFlex.phpapp/Services/Activity/HubSpot/Service.phpapp/Services/Crm/Hubspot/Client.phpapp/Services/Crm/Hubspot/HubspotClientInterface.phpapp/Services/Crm/Hubspot/Pagination/HubspotPaginationService.phpapp/Services/Crm/Hubspot/Pagination/PaginationState.phpdatabase/migrations/2026_05_13_124153_create_mcp_feature_flag.phptests/Feature/Mcp/GetMeToolFeatureTest.phptests/Feature/Mcp/ListCallsToolFeatureTest.phptests/Feature/Mcp/McpTestHelpersTrait.phptests/Unit/Component/ES/ChunkSizeTest.phptests/Unit/Component/ES/Processor/DT0s/SelectionListTest.phptests/Unit/Component/ES/Processor/TargetEntitiesSelectorTest.phptests/Unit/Component/MeetingBot/Service/ParticipantMatcherTest.phptests/Unit/Exceptions/RateLimitExceptionTest.phptests/Unit/Jobs/Crm/MatchActivityCrmDataTest.phptests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phptests/Unit/Services/Activity/HubSpot/ServiceTest.phptests/Unit/Services/Crm/Hubspot/ClientTest.phptests/Unit/Services/Crm/Hubspot/Pagination/HubspotPaginationServiceTest.php97++++++-132++++++•15++++++21++++--2+-25++++++.140++++++-2+-19++++++50++++++-27++++++139++++++-6856++++++-+-151++++++-109++++++-250++++++-283++++++=37 files changed, 1587 insertions(+), 344 deletions(-)create mode 100644 app/Component/ES/ChunkSize.phpcreate mode 100644 app/Jobs/Middleware/HandleHubspotRateLimit.phpcreate mode 100644 app/Mcp/Tools/GetMeTool.phpcreate mode 100644 database/migrations/2026_05_13_124153_create_mcp_feature_flag.phpcreate mode 100644 tests/Feature/Mcp/GetMeToolFeatureTest.phpcreate mode 100644 tests/Unit/Component/ES/ChunkSizeTest.phpcreate mode 100644 tests/Unit/Exceptions/RateLimitExceptionTest.phpcreate mode 100644 tests/Unit/Jobs/Middleware/HandleHubspotRateLimitTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ git pullAlready up to date.lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ co -b JY-20676-delete-reSwitched to a new branch 'JY-20676-delete-report-related-objects'lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20676-delete-report-related-obHomeDMsActivityFilesLaterMoreEDJiminny ...# Jiminny-Dg# platform-tickets# product_launches# random# releases# sofia-office# support# thank-yous# the_people_of jimi...• Direct messages€. Vasil VasilevP. Nikolay Yankov%. Galya Dimitrova L. Aneliya Angelovaão Stefka StoyanovaStoyan Tomovd Todor Stamatov "Kd. Mario GeorgievNikolay Ivanovdo James Graham2 Stoyan TanevRo Steliyan GeorgievLukas Kovalik y…..AppsJira CloudToastSupport Daily • in 3h 54 m100% CTue 19 May 11:06:49QDescribe what you are looking for# the_people_of jimi...8 426 0• MessagesQ Files+Stefka Stoyanov:Today ~Hі Eteam,I wanted to share that our Lead Developer llianKyuchukov has decided to move on from Jiminny topursue a new opportunity. While we're really sad tosee them go, we're also excited for him and thisnext chapter in his professional journey.llian's last working day will be 14 July, so we stillhave some time together before then. Over thecoming weeks, please make the most of hisknowledge, experience, and context so we canensure a smooth transition across the team.It's hard to overstate the impact llian has had here- from shaping the product and solving toughproblems to supporting teammates and helpingbuild the product we have today. We re incrediblygrateful for everything he contributed over this 2years he was with & engineering team.Just wanted to share the news openly witheveryone and say a huge thanks to llian foreverything so far. Vou Please join me in wishing himall the very best for what comes next.We start looking for a Full-Stack Software Engineer,so if you know anyone you believe will fit, pleasecontact me or Mira directly A® 42Message #the_people_of_jiminny+...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56455
|
1967
|
44
|
2026-05-19T08:06:51.853760+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178011853_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4508527917909716569
|
-8683903597217656915
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
56453
|
NULL
|
NULL
|
NULL
|
|
56456
|
1966
|
33
|
2026-05-19T08:06:53.177266+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178013177_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4508527917909716569
|
-8683903597217656915
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
56454
|
NULL
|
NULL
|
NULL
|
|
56457
|
1967
|
45
|
2026-05-19T08:06:53.212571+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178013212_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-351575931525056321
|
-8132358351805502526
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
iilPhostormVIewINavicareCodeLaravelKeractorTOOISFV faVsco.js?9 JY-20676-delete-report-related-objectsProiect vC) AutomatedReport.onpTeamRetentionPolicyFeatureTest.php" ThemeTopicUpdateFeatureTest.phpUserOnboardFeatureTest.php© AskAnythingPrompt.php› Intearation© ScimProvisioning.phpw Services© SyncActivity.phpccrm/close/service.oho?DStuosv M Unitclass ASKAnyth1ngPromptServ1celest extends TestcasepubLICtunction testlelete.skanvthino?romoto: vozo> Actions• Component> ActionltemsethodNames. 'upaace')->onceActivitv->with(['ask_anything_prompt_id' => null]);› ActivityAnalyticsM ActivitvSearch->with(['ask_anything_prompt_id' => null, 'status' => falsel);AiActivityTypeTM AiAutomation330Soromot->exoects(sthis->onceOblD AiCallScoring• M AskAnything->method constraint:'automatedRenorts')332->wil Return(SrelationMocka:©) AskAnythingPromptServiceTest.phpch HistorvServicelest.ong334)M Ack liminnyAil$user = $this->createMockosusen-seyrectef2.edits.ton/ v Accept File &X Reiect File 42 G+ 7 of 7 files →->methodd constraint: "aettd")Local ChandesConsoleLooXv Changes 10 files=.env.local app© ActivityController.php app/Http/Controllers/APISide-by-side viewerDo not ignore5604af40 app/Models/AskAnything/AskAnythingPrompt.phpcAsKAnythinaPrompt.php app/Models/ASKAnyth'target',c) AsKAnvihinaPromotbto.ono apo/comoonent/AskAnvihino/Dros'owner_id',© AskAnvthinaPromptService.php app/Component/AskAnvthing@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthina© Ask.JiminnvReportsController.pho app/Htto/Controllers/API/V2C)JiminnvDebuaCommand.oho apo/Console/Commands.protected Svisible =Ititlelphp logging.php configC) Search.nhn anr/Models/Activitv.• Unversioned Files 9 filesi=env.nikilocal annE .env.other appc) CanAccessAiRenortsTest.oho tests/Unit/Policie.public function getContentÖ: stringreturn Sthis->getAttribute('content'):(C) CreateMockAsk.liminnvRenortResultCommand.ohn ann/Console/Commands/Re favicon.ico nublic= ide tut andTraw_sqL_query.sql app@ SimulateWebhooksCommand.php app/Console/Commands/Crm/HubsporM4 WEBHOOK_FILTERING_IMPLEMENTATION.md app(c) Search.onpC) ActivityController.onpAccept ReiectHighlight words"= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~29 €public function shouldApplyQueries: boolf...}34 6t >public function getQueries: FilterDefinitionOueryCollection{...}45 6tpublic function toArrav@): arravf...}1 usage118private function getOptions(): array(...}public function getValue: arrayt...1301 usage1311private function getDefaultValue: arrayt..._135_136 C >public function getValidationRules(?string $prefix = null): arrayf...}Current version(Jiminny|Models\AskAnything > AskAnythingPromp'target',lownen 1dtprotected Sappends =['has_reports',protected Svisible =[concentwner id'public function getContent@: stringreturn Sthis->getAttribute('content'):nublic function getHasReportsAttribute(: boollreturn Sthis->automatedRenorts()->exists@="suppont Dally • In 3n 04m100% 5• Tue 19 May 11:06:52AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report M+0 ..mocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 — In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.odl "8 files 400-7 )* Reject allAccent alliAsk anvthina (4D1+ <> Code Claude Opus 4.7 Medium•01.2 differencesThe Hunsnell nluain hac hearies for other lanquades (todav 10-00)WN Windsurf Toams 228-1UTF.8ih 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56458
|
1967
|
46
|
2026-05-19T08:06:54.701811+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178014701_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptServiceTest.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Unit\\Component\\AskAnything;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Jiminny\\Component\\AskAnything\\AskAnythingPromptService;\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\nuse PHPUnit\\Framework\\MockObject\\MockObject;\nuse Tests\\TestCase;\nuse Tests\\Unit\\Traits\\TestPrivateMethod;\n\nclass AskAnythingPromptServiceTest extends TestCase\n{\n use TestPrivateMethod;\n\n private AskAnythingPromptService $askAnythingPromptService;\n private AskAnythingRepository&MockObject $askAnythingRepository;\n private UserRepository&MockObject $userRepository;\n private GroupRepositoryInterface&MockObject $groupRepository;\n\n protected function setUp(): void\n {\n $this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);\n $this->userRepository = $this->createMock(UserRepository::class);\n $this->groupRepository = $this->createMock(GroupRepositoryInterface::class);\n\n $this->askAnythingPromptService = new AskAnythingPromptService(\n $this->askAnythingRepository,\n $this->userRepository,\n $this->groupRepository\n );\n }\n\n public function testGetAskAnythingPrompts(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $user->expects($this->any())\n ->method('getUuid')\n ->willReturn('1');\n $defaultPrompt = $this->createMock(AskAnythingPrompt::class);\n $defaultPrompt->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUser->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('First users prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt');\n $promptOwnedByUser->expects($this->once())\n ->method('getId')\n ->willReturn(99);\n $promptOwnedByUser->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getOwner')\n ->willReturn(null);\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getUuid')\n ->willReturn('default-uuid');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getTitle')\n ->willReturn('Sentiment');\n $defaultPromptOrderedByUser->expects($this->once())\n ->method('getContent')\n ->willReturn('What was the overall sentiment of the customer during the call?');\n $promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);\n $promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))\n ->method('getOwner')\n ->willReturn($user);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-2nd-prompt');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getTitle')\n ->willReturn('Prompt shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getContent')\n ->willReturn('Test prompt that is shared with group');\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getId')\n ->willReturn(109);\n $promptOwnedByUserAndSharedWithGroup->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n $group = $this->createMock(Group::class);\n $group->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-group');\n $sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);\n $sharedWithGroup->expects($this->once())\n ->method('getUser')\n ->willReturn(null);\n $sharedWithGroup->expects($this->once())\n ->method('getGroup')\n ->willReturn($group);\n\n $this->askAnythingRepository->expects($this->exactly(2))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [99, new Collection([])],\n [109, new Collection([$sharedWithGroup])],\n ]);\n\n $prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];\n $this->askAnythingRepository->expects($this->once())\n ->method('findPromptsByUserAndTarget')\n ->willReturn(new Collection($prompts));\n\n $expectedDto1 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto2 = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n 'First users prompt',\n 'Test prompt',\n AskAnythingPromptTarget::call,\n '1',\n [],\n [],\n );\n $expectedDto3 = new AskAnythingPromptDto(\n 'default-uuid',\n 'Sentiment',\n 'What was the overall sentiment of the customer during the call?',\n AskAnythingPromptTarget::call\n );\n $expectedDto4 = new AskAnythingPromptDto(\n 'uuid-2nd-prompt',\n 'Prompt shared with group',\n 'Test prompt that is shared with group',\n AskAnythingPromptTarget::call,\n '1',\n [],\n ['uuid-of-the-group'],\n );\n $dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);\n\n $this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);\n }\n\n public function testEditAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(123);\n $prompt->expects($this->never())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(123);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('owner-uuid');\n\n $title = 'new title';\n $content = 'new content';\n $shareUsers = ['us-1'];\n $shareGroups = ['gr-1', 'gr-2'];\n\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $shareGroup1 = $this->createMock(Group::class);\n $shareGroup2 = $this->createMock(Group::class);\n $this->groupRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['gr-1', $shareGroup1],\n ['gr-2', $shareGroup2],\n ]);\n\n $editPrompt = $this->createMock(AskAnythingPrompt::class);\n $editPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $editPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $editPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $editPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $this->askAnythingRepository->expects($this->once())\n ->method('editPrompt')\n ->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])\n ->willReturn($editPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'owner-uuid',\n $shareUsers,\n $shareGroups\n );\n $editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $editDto);\n }\n\n public function testHideDefaultAndCreateAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('new-owner-uuid');\n $title = 'title';\n $content = 'content';\n $shareUsers = ['us-1'];\n $shareGroups = [];\n $shareUser = $this->createMock(User::class);\n $this->userRepository->expects($this->once())\n ->method('findByUuid')\n ->with('us-1')\n ->willReturn($shareUser);\n $this->groupRepository->expects($this->never())\n ->method('findByUuid');\n\n $newPrompt = $this->createMock(AskAnythingPrompt::class);\n $newPrompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $newPrompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-1st-prompt');\n $newPrompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $newPrompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->willReturn($newPrompt);\n\n $expectedDto = new AskAnythingPromptDto(\n 'uuid-1st-prompt',\n $title,\n $content,\n AskAnythingPromptTarget::call,\n 'new-owner-uuid',\n $shareUsers,\n $shareGroups\n );\n\n $actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);\n\n $this->assertEquals($expectedDto, $actualDto);\n }\n\n public function testDeleteAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n\n // Use Mockery for the relationship mock (more flexible)\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->any())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([]));\n $this->askAnythingRepository->expects($this->once())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteAskAnythingPromptWithRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $user = $this->createMock(User::class);\n $user->expects($this->any())\n ->method('getId')\n ->willReturn(1);\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(1, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('findSharedUsersAndGroupsByPromptId')\n ->willReturnMap([\n [1, new Collection([$userPrompt])],\n [1, new Collection([])],\n ]);\n $this->askAnythingRepository->expects($this->never())\n ->method('deletePrompt');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideDefaultAskAnythingPrompt(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(true);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser');\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(3))\n ->method('getId')\n ->willReturn(33);\n\n $relationMock = \\Mockery::mock(\\Illuminate\\Database\\Eloquent\\Relations\\HasMany::class);\n $relationMock->shouldReceive('withTrashed')\n ->once()\n ->andReturnSelf();\n $relationMock->shouldReceive('update')\n ->once()\n ->with(['ask_anything_prompt_id' => null, 'status' => false]);\n $prompt->expects($this->once())\n ->method('automatedReports')\n ->willReturn($relationMock);\n\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->once())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(33)\n ->willReturn(new Collection([]));\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testHideSharedWithGroupAskAnythingPrompt(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn($userPrompt);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->once())\n ->method('hidePromptForUser')\n ->with($prompt, $user);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testDeleteWithNoSharesAndNotOwner(): void\n {\n $userPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('isDefaultPrompt')\n ->willReturn(false);\n $prompt->expects($this->once())\n ->method('getOwnerId')\n ->willReturn(1);\n $prompt->expects($this->exactly(2))\n ->method('getId')\n ->willReturn(33);\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getId')\n ->willReturn(2);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUser')\n ->with(33, $user)\n ->willReturn(null);\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedPromptByUserGroup')\n ->with(33, $user)\n ->willReturn(null);\n $userPrompt->expects($this->never())\n ->method('delete');\n $this->askAnythingRepository->expects($this->never())\n ->method('hidePromptForUser');\n\n $this->expectException(\\InvalidArgumentException::class);\n\n $this->askAnythingPromptService->delete($prompt, $user);\n }\n\n public function testReorderAskAnythingPrompts(): void\n {\n $prompts = ['id1', 'id2', 'id3'];\n $prompt1 = $this->createMock(AskAnythingPrompt::class);\n $prompt2 = $this->createMock(AskAnythingPrompt::class);\n $prompt3 = $this->createMock(AskAnythingPrompt::class);\n $user = $this->createMock(User::class);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('getPromptByUuid')\n ->willReturnMap([\n ['id1', $prompt1],\n ['id2', $prompt2],\n ['id3', $prompt3],\n ]);\n $this->askAnythingRepository->expects($this->exactly(3))\n ->method('orderPromptForUser')\n ->willReturnMap([\n [[$prompt1, $user, 1]],\n [[$prompt2, $user, 2]],\n [[$prompt3, $user, 3]],\n ]);\n $this->askAnythingPromptService->reorder($user, $prompts);\n }\n\n public function testCreateAskAnythingPromptWithTwoUsers(): void\n {\n $user = $this->createMock(User::class);\n $user->expects($this->once())\n ->method('getUuid')\n ->willReturn('uuid-of-the-user');\n $shareUser1 = $this->createMock(User::class);\n $shareUser2 = $this->createMock(User::class);\n $title = 'Test title';\n $content = 'Test content';\n $target = AskAnythingPromptTarget::call;\n $shareUsers = ['us-1', 'us-2'];\n $shareGroups = [];\n\n $this->userRepository->expects($this->exactly(2))\n ->method('findByUuid')\n ->willReturnMap([\n ['us-1', $shareUser1],\n ['us-2', $shareUser2],\n ]);\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getUuid')\n ->willReturn('prompt-1-uuid');\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn($title);\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn($content);\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt')\n ->with(\n $user,\n $target,\n $title,\n $content,\n [$shareUser1, $shareUser2],\n [],\n )\n ->willReturn($prompt);\n\n $expectedPromptDto = new AskAnythingPromptDto(\n 'prompt-1-uuid',\n $title,\n $content,\n $target,\n 'uuid-of-the-user',\n $shareUsers,\n $shareGroups,\n );\n\n $actualPromptDto = $this->askAnythingPromptService->create(\n $user,\n $title,\n $content,\n $target,\n $shareUsers,\n $shareGroups\n );\n\n $this->assertEquals($expectedPromptDto, $actualPromptDto);\n }\n\n public function testRecreatePromptsForUserRelations(): void\n {\n $prompt = $this->createMock(AskAnythingPrompt::class);\n $prompt->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n $prompt->expects($this->once())\n ->method('getTarget')\n ->willReturn(AskAnythingPromptTarget::call);\n $prompt->expects($this->once())\n ->method('getTitle')\n ->willReturn('Test title');\n $prompt->expects($this->once())\n ->method('getContent')\n ->willReturn('Test content');\n\n $sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);\n $sharedUser = $this->createMock(User::class);\n $sharedUser->expects($this->once())\n ->method('isStatusActive')\n ->willReturn(true);\n $sharedUser->expects($this->once())\n ->method('getId')\n ->willReturn(1);\n\n $sharedPrompt->expects($this->once())\n ->method('getUser')\n ->willReturn($sharedUser);\n $sharedPrompt->expects($this->exactly(2))\n ->method('isRemoved')\n ->willReturn(false);\n $sharedPrompt->expects($this->once())\n ->method('delete');\n\n $this->askAnythingRepository->expects($this->once())\n ->method('findSharedUsersAndGroupsByPromptId')\n ->with(1)\n ->willReturn(new Collection([$sharedPrompt]));\n\n $this->askAnythingRepository->expects($this->once())\n ->method('createPrompt');\n\n $data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);\n\n $this->assertEquals([[1], []], $data);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-4508527917909716569
|
-8683903597217656915
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Tests\Unit\Component\AskAnything;
use Illuminate\Database\Eloquent\Collection;
use Jiminny\Component\AskAnything\AskAnythingPromptService;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\TestCase;
use Tests\Unit\Traits\TestPrivateMethod;
class AskAnythingPromptServiceTest extends TestCase
{
use TestPrivateMethod;
private AskAnythingPromptService $askAnythingPromptService;
private AskAnythingRepository&MockObject $askAnythingRepository;
private UserRepository&MockObject $userRepository;
private GroupRepositoryInterface&MockObject $groupRepository;
protected function setUp(): void
{
$this->askAnythingRepository = $this->createMock(AskAnythingRepository::class);
$this->userRepository = $this->createMock(UserRepository::class);
$this->groupRepository = $this->createMock(GroupRepositoryInterface::class);
$this->askAnythingPromptService = new AskAnythingPromptService(
$this->askAnythingRepository,
$this->userRepository,
$this->groupRepository
);
}
public function testGetAskAnythingPrompts(): void
{
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$user->expects($this->any())
->method('getUuid')
->willReturn('1');
$defaultPrompt = $this->createMock(AskAnythingPrompt::class);
$defaultPrompt->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPrompt->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPrompt->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPrompt->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUser = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUser->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUser->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$promptOwnedByUser->expects($this->once())
->method('getTitle')
->willReturn('First users prompt');
$promptOwnedByUser->expects($this->once())
->method('getContent')
->willReturn('Test prompt');
$promptOwnedByUser->expects($this->once())
->method('getId')
->willReturn(99);
$promptOwnedByUser->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$defaultPromptOrderedByUser = $this->createMock(AskAnythingPrompt::class);
$defaultPromptOrderedByUser->expects($this->once())
->method('getOwner')
->willReturn(null);
$defaultPromptOrderedByUser->expects($this->once())
->method('getUuid')
->willReturn('default-uuid');
$defaultPromptOrderedByUser->expects($this->once())
->method('getTitle')
->willReturn('Sentiment');
$defaultPromptOrderedByUser->expects($this->once())
->method('getContent')
->willReturn('What was the overall sentiment of the customer during the call?');
$promptOwnedByUserAndSharedWithGroup = $this->createMock(AskAnythingPrompt::class);
$promptOwnedByUserAndSharedWithGroup->expects($this->exactly(2))
->method('getOwner')
->willReturn($user);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getUuid')
->willReturn('uuid-2nd-prompt');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getTitle')
->willReturn('Prompt shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getContent')
->willReturn('Test prompt that is shared with group');
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getId')
->willReturn(109);
$promptOwnedByUserAndSharedWithGroup->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$group = $this->createMock(Group::class);
$group->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-group');
$sharedWithGroup = $this->createMock(UserAskAnythingPrompt::class);
$sharedWithGroup->expects($this->once())
->method('getUser')
->willReturn(null);
$sharedWithGroup->expects($this->once())
->method('getGroup')
->willReturn($group);
$this->askAnythingRepository->expects($this->exactly(2))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[99, new Collection([])],
[109, new Collection([$sharedWithGroup])],
]);
$prompts = [$defaultPrompt, $promptOwnedByUser, $defaultPromptOrderedByUser, $promptOwnedByUserAndSharedWithGroup];
$this->askAnythingRepository->expects($this->once())
->method('findPromptsByUserAndTarget')
->willReturn(new Collection($prompts));
$expectedDto1 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto2 = new AskAnythingPromptDto(
'uuid-1st-prompt',
'First users prompt',
'Test prompt',
AskAnythingPromptTarget::call,
'1',
[],
[],
);
$expectedDto3 = new AskAnythingPromptDto(
'default-uuid',
'Sentiment',
'What was the overall sentiment of the customer during the call?',
AskAnythingPromptTarget::call
);
$expectedDto4 = new AskAnythingPromptDto(
'uuid-2nd-prompt',
'Prompt shared with group',
'Test prompt that is shared with group',
AskAnythingPromptTarget::call,
'1',
[],
['uuid-of-the-group'],
);
$dtos = $this->askAnythingPromptService->get($user, AskAnythingPromptTarget::call);
$this->assertEquals([$expectedDto1, $expectedDto2, $expectedDto3, $expectedDto4], $dtos);
}
public function testEditAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(123);
$prompt->expects($this->never())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(123);
$user->expects($this->once())
->method('getUuid')
->willReturn('owner-uuid');
$title = 'new title';
$content = 'new content';
$shareUsers = ['us-1'];
$shareGroups = ['gr-1', 'gr-2'];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$shareGroup1 = $this->createMock(Group::class);
$shareGroup2 = $this->createMock(Group::class);
$this->groupRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['gr-1', $shareGroup1],
['gr-2', $shareGroup2],
]);
$editPrompt = $this->createMock(AskAnythingPrompt::class);
$editPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$editPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$editPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$editPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$this->askAnythingRepository->expects($this->once())
->method('editPrompt')
->with($prompt, $title, $content, [$shareUser], [$shareGroup1, $shareGroup2])
->willReturn($editPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'owner-uuid',
$shareUsers,
$shareGroups
);
$editDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $editDto);
}
public function testHideDefaultAndCreateAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('new-owner-uuid');
$title = 'title';
$content = 'content';
$shareUsers = ['us-1'];
$shareGroups = [];
$shareUser = $this->createMock(User::class);
$this->userRepository->expects($this->once())
->method('findByUuid')
->with('us-1')
->willReturn($shareUser);
$this->groupRepository->expects($this->never())
->method('findByUuid');
$newPrompt = $this->createMock(AskAnythingPrompt::class);
$newPrompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$newPrompt->expects($this->once())
->method('getUuid')
->willReturn('uuid-1st-prompt');
$newPrompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$newPrompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->willReturn($newPrompt);
$expectedDto = new AskAnythingPromptDto(
'uuid-1st-prompt',
$title,
$content,
AskAnythingPromptTarget::call,
'new-owner-uuid',
$shareUsers,
$shareGroups
);
$actualDto = $this->askAnythingPromptService->edit($prompt, $user, $title, $content, $shareUsers, $shareGroups);
$this->assertEquals($expectedDto, $actualDto);
}
public function testDeleteAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
// Use Mockery for the relationship mock (more flexible)
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->any())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([]));
$this->askAnythingRepository->expects($this->once())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteAskAnythingPromptWithRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->any())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getId')
->willReturn(1);
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(1, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->exactly(3))
->method('findSharedUsersAndGroupsByPromptId')
->willReturnMap([
[1, new Collection([$userPrompt])],
[1, new Collection([])],
]);
$this->askAnythingRepository->expects($this->never())
->method('deletePrompt');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideDefaultAskAnythingPrompt(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(true);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser');
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(3))
->method('getId')
->willReturn(33);
$relationMock = \Mockery::mock(\Illuminate\Database\Eloquent\Relations\HasMany::class);
$relationMock->shouldReceive('withTrashed')
->once()
->andReturnSelf();
$relationMock->shouldReceive('update')
->once()
->with(['ask_anything_prompt_id' => null, 'status' => false]);
$prompt->expects($this->once())
->method('automatedReports')
->willReturn($relationMock);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(33)
->willReturn(new Collection([]));
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithUserAndGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn($userPrompt);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testHideSharedWithGroupAskAnythingPrompt(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn($userPrompt);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('hidePromptForUser')
->with($prompt, $user);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testDeleteWithNoSharesAndNotOwner(): void
{
$userPrompt = $this->createMock(UserAskAnythingPrompt::class);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('isDefaultPrompt')
->willReturn(false);
$prompt->expects($this->once())
->method('getOwnerId')
->willReturn(1);
$prompt->expects($this->exactly(2))
->method('getId')
->willReturn(33);
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getId')
->willReturn(2);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUser')
->with(33, $user)
->willReturn(null);
$this->askAnythingRepository->expects($this->once())
->method('findSharedPromptByUserGroup')
->with(33, $user)
->willReturn(null);
$userPrompt->expects($this->never())
->method('delete');
$this->askAnythingRepository->expects($this->never())
->method('hidePromptForUser');
$this->expectException(\InvalidArgumentException::class);
$this->askAnythingPromptService->delete($prompt, $user);
}
public function testReorderAskAnythingPrompts(): void
{
$prompts = ['id1', 'id2', 'id3'];
$prompt1 = $this->createMock(AskAnythingPrompt::class);
$prompt2 = $this->createMock(AskAnythingPrompt::class);
$prompt3 = $this->createMock(AskAnythingPrompt::class);
$user = $this->createMock(User::class);
$this->askAnythingRepository->expects($this->exactly(3))
->method('getPromptByUuid')
->willReturnMap([
['id1', $prompt1],
['id2', $prompt2],
['id3', $prompt3],
]);
$this->askAnythingRepository->expects($this->exactly(3))
->method('orderPromptForUser')
->willReturnMap([
[[$prompt1, $user, 1]],
[[$prompt2, $user, 2]],
[[$prompt3, $user, 3]],
]);
$this->askAnythingPromptService->reorder($user, $prompts);
}
public function testCreateAskAnythingPromptWithTwoUsers(): void
{
$user = $this->createMock(User::class);
$user->expects($this->once())
->method('getUuid')
->willReturn('uuid-of-the-user');
$shareUser1 = $this->createMock(User::class);
$shareUser2 = $this->createMock(User::class);
$title = 'Test title';
$content = 'Test content';
$target = AskAnythingPromptTarget::call;
$shareUsers = ['us-1', 'us-2'];
$shareGroups = [];
$this->userRepository->expects($this->exactly(2))
->method('findByUuid')
->willReturnMap([
['us-1', $shareUser1],
['us-2', $shareUser2],
]);
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getUuid')
->willReturn('prompt-1-uuid');
$prompt->expects($this->once())
->method('getTitle')
->willReturn($title);
$prompt->expects($this->once())
->method('getContent')
->willReturn($content);
$this->askAnythingRepository->expects($this->once())
->method('createPrompt')
->with(
$user,
$target,
$title,
$content,
[$shareUser1, $shareUser2],
[],
)
->willReturn($prompt);
$expectedPromptDto = new AskAnythingPromptDto(
'prompt-1-uuid',
$title,
$content,
$target,
'uuid-of-the-user',
$shareUsers,
$shareGroups,
);
$actualPromptDto = $this->askAnythingPromptService->create(
$user,
$title,
$content,
$target,
$shareUsers,
$shareGroups
);
$this->assertEquals($expectedPromptDto, $actualPromptDto);
}
public function testRecreatePromptsForUserRelations(): void
{
$prompt = $this->createMock(AskAnythingPrompt::class);
$prompt->expects($this->once())
->method('getId')
->willReturn(1);
$prompt->expects($this->once())
->method('getTarget')
->willReturn(AskAnythingPromptTarget::call);
$prompt->expects($this->once())
->method('getTitle')
->willReturn('Test title');
$prompt->expects($this->once())
->method('getContent')
->willReturn('Test content');
$sharedPrompt = $this->createMock(UserAskAnythingPrompt::class);
$sharedUser = $this->createMock(User::class);
$sharedUser->expects($this->once())
->method('isStatusActive')
->willReturn(true);
$sharedUser->expects($this->once())
->method('getId')
->willReturn(1);
$sharedPrompt->expects($this->once())
->method('getUser')
->willReturn($sharedUser);
$sharedPrompt->expects($this->exactly(2))
->method('isRemoved')
->willReturn(false);
$sharedPrompt->expects($this->once())
->method('delete');
$this->askAnythingRepository->expects($this->once())
->method('findSharedUsersAndGroupsByPromptId')
->with(1)
->willReturn(new Collection([$sharedPrompt]));
$this->askAnythingRepository->expects($this->once())
->method('createPrompt');
$data = $this->invokePrivateMethod('recreatePromptsForUserRelations', $this->askAnythingPromptService, [$prompt]);
$this->assertEquals([[1], []], $data);
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
56457
|
NULL
|
NULL
|
NULL
|
|
56459
|
1966
|
34
|
2026-05-19T08:07:01.234770+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178021234_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
-5652292588814399120
|
1126372201043036670
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56460
|
1967
|
47
|
2026-05-19T08:07:01.270066+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178021270_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
3921796768863820486
|
-8634233732034220862
|
click
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
PhostormVIewINavicarecodeLaravelKeractorTOOISWindowFV faVsco.js?9 JY-20676-delete-report-related-objectsProletey(C) AutomatedReport.onp© AskAnythingPromptServiceTest.php© Search.php= custom.log= laravel.log4 SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euy© AskAnythingPromptDto.phpD Events© AsKAnytningPromptservice.ong© AskAnythingPrompt.phpAskAnytingPromptuto.pnp© ActivityController.phpA console [STAGING]© CoachingFeedbackCoachUserln.php XC) SoftPhoneManager.png© Constants.phpfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~c Historyservice.ongD AskJiminnyAiWAWS0 BillingManagementu cachescimprovisioning.phpC Coreuser.phpC) Acuivity/Close/service.pnpsyncacuivity.onoccrm/close/service.oho29 6tpublic function shouldApplyQueries: boolf...}class AskanythingPromptservicepublic function get(user suser, ASkAnythingPromptlarget starget): array34 6t >public function getQueries: FilterDefinitionQueryCollection{...}45 6tw countrysowneruuld,pubLic function toArrayo): arrayi...hDatabase1 usage→ DatadogDatettime59soromot->has redorts.Accept Rejectprivate function getOptions: arrayt...DealinsiahtsN DealRisks1N GlasticSearchM EloquentEncoding• EncryptionTMES119130public function getValue: arrayt...return Soromotitos:lusageT 1 of 4 edits + Accept File &+X Reject File 0%e+ S of7 files →131135136 >private function getDefaultValue@: arrayt...public function getValidationRules(?string $prefix = null): array{...}* Qnaram arnau<strina> SchanolisenclluidoLocal ChandesLooXChanges 10 tilesL8<→# Side-by-side viewerDo not ignoreHighlight words"X B5 t?= .env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnything@ AskAnvthinaPromptDto.php app/Component/AskAnvthina/Dtos8 5604af40 app/Componen As,Current versionC)AskAnvthinaPromotService.ono apo/Co@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthinaC)AskJiminnvRenortsController.oho apo/Htto/Controllers/APIV2return Soromotitos:C)JiminnvDebuaCommand.oh apo/Console/Commands)return $promptDtos;/Jliminnv Comnonent AskAnvthina > AskAnvthinaPromntService > create! /php logging.php configC) Search.nhn anr/Models/ActivitvnnvComnonent|AskAnvthina > AskAnvthinaPromotService > createlAAUStarget,Sucen->oetlluido• Unversioned Files 9 filesi=env.nikilocal annE .env.other appc) CanAccessAiRenortsTest.oho tests/Unit/Policies$shareUsersUuids,$shareGroupsUuidsStarget,Suser->getUuid)$shareUsersUuids,$shareGroupsUuids.$prompt->has reports(C) CreateMockAsk.liminnvRenortResultCommand.ohn ann/Console/Commands/Re favicon.ico nublicE ids.txt appTraw sall query.sal app@ SimulateWebhooksCommand.php app/Console/Commands/Crm/HubsporM4 WEBHOOK_FILTERING_IMPLEMENTATION.md appSnewPrompt->getTargetoSuser->qetUu1dolSshareUsersUuids\Jiminny|Component\AskAnything > AskAnythingPrSnewPromot->getTarget(.Suser->getUuidoSshareGroupsUuidsSshareUsersUuidsSshareGroupsUuidsSnewPromot->has reportsnublic function deletednublic function deletednrivate function deletePromottfNoRelations(AskAnvthinaPromot Soromot): voidian vol can cafelv uninctall Huncnell without affertina the dirtionariec for other lanquaaec (today 10:00)• suppont Dally • In 3n 04m100% 5• Tue 19 May 11:07:00AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report Mmocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 - In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.* Reject allAccent allAsk anvthina (4D1+ <> Code Claude Opus 4.7 Medium•01.4 difterencesW Windsurf Teams50-1UTE-Rf 4 spaces...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56461
|
1967
|
48
|
2026-05-19T08:07:03.757391+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178023757_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-6966022010367698874
|
-564708849257816637
|
visual_change
|
hybrid
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
PhostormVIeWINavicarecodeKeractorFV faVsco.js?9 JY-20676-delete-report-related-objectsroledeyAskAnythingPromptService.phpD AskAnything© AskAnythingPromptServiceTest.phpv D Dtos© AskAnythingPromptDto.phpD eventsconstants.php© AskAnythingPromptService.phpchistorvservice.ono0 AskJiminnyAiD AWSw cachew country1 customerAo1 Database→ DatadogN DateTtimeN DealinsiahtsN DealRisksIM SlacticSearchM SloquentM EncodindLocal ChandecLooXChanges 10 tiles= .env.local app© ActivityController.php app/Http/Controllers/API© AskAnythingPrompt.php app/Models/AskAnythingC) ASKAnvihinaPromotbto,ono apo/comoonent/AskAnvihino/DrosC)AskAnvthinaPromotService.ono apo/C@ AskAnvthinaPromptServiceTest.php tests/Unit/Component/AskAnvthinaC)AskJiminnvRenortsController.oho apo/Htto/Controllers/APIV2C)JiminnvDebuaCommand.oh apo/Console/Commands)php logging.php configC) Search.nhn anr/Models/Activitv.• Unversioned Files 9 filesi=env.nikilocal annE .env.other appci CanAccessAiRenortsTest.oho tests/Unit/Policies(C) CreateMockAsk.liminnvRenortResultCommand.ohn ann/Console/Commands/Re favicon.ico nublic= ide tyt andTraw sall query.sal app@ SimulateWebhooksCommand.php app/Console/Commands/Crm/HubsporM4 WEBHOOK_FILTERING_IMPLEMENTATION.md app© AskJiminnyReportsController.php© AskAnythingPromptDto.php© SoftPhoneManager.php©Activity/Close/service.pnp© Activity/RingCentral/Service.php= custom.log= laravel.log« SF jiminny@localhost]4 HS_local [jiminny@localhost]& console [PROD]# console [euyA console [STAGING]© CoachingFeedbackCoachUserln.php Xfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefini~29 6t34 6t >45 6t136 >public function shouldApplyQueries: boolf...}public function getQueries: FilterDefinitionQueryCollection{...}pubLic function toArray): arrayl...л1 usageprivate function getOptions: arrayt...public function getValue: arrayt...lusageprivate function getDefaultValue: arrayt...public function getValidationRules(?string $prefix = null): array{...}Current version• suppont Dally • In 3n 03m100% 5• Tue 19 May 11:07:03AskJiminnyReportActivityServiceTest vCascadeAsk Jiminny Report Mmocd → null, "status → Talsel3. loggle validationrtsController.php: 126-169 - In toggleStatus(), when enabled=true and the report is an Ask Jiminnyreport, returns 422 lt elther activity search 1d or ask anything prompt 1d is nult . Disabling is always allowed.4. TestsAskAnythingPromptServiceTest.php - Updated two existing update() mock expectations to match the new payload ( ['aPer your rules i did not add unit tests for the controller. The existing SavedSearchCRUDFeatureTest covers the searchdelete tlow: backend service test covers promot delete pavload.Ask anvthina (4D1+ <> Code Claude Opus 4.7 Medium• 1 of 2 editsJX Reiect File 49g+ 3 of7 files →< → @ Side-by-side viewer -Do not ignoreHighlight wordsx 15 ?8 5604af40 app/Componen As,return Soromotitos:nnvComnonent|AskAnvthina > AskAnvthinaPromotService > create lAAStarget,Sucen-saetlluido$shareUsersUuids,$shareGroupsUuidsSnewPrompt->getTargetoSuser->getUuidoSshareUsersUuids.SshareGroupsUuidsnublic function deletednrivate function deletePromottfNoRelations(AskAnvthinaPromot Soromot): voidelv uninctall Huncnell without affertina the dirtionariec for other lanquages (todev 10:00)* Reject allAccent all•01.4 difterencesreturn $promptDtos;/Jliminnv Comnonent AskAnvthina > AskAnvthinaPromntService > create! /Starget,Suser->getUuid)$shareUsersUuids,$shareGroupsUuids.$prompt->has reports\Jiminny|Component\AskAnything > AskAnythingPSnewPromot->getTarget(.Suser->getUuidoSshareUsersUuidsSshareGroupsUuidsSnewPromot->has reportsnublic function deleted19:1UTF-8f 4 spaces...
|
56460
|
NULL
|
NULL
|
NULL
|
|
56462
|
1967
|
49
|
2026-05-19T08:07:06.729207+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178026729_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.007978723,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.007978723,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7287234,"top":0.09896249,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
395026636455006835
|
1126917008115010046
|
visual_change
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
56463
|
1966
|
35
|
2026-05-19T08:07:07.785983+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178027785_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.016666668,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.016666668,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.014583333,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
8546892631511200949
|
1126354058161588734
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected...
|
56459
|
NULL
|
NULL
|
NULL
|
|
56464
|
1967
|
50
|
2026-05-19T08:07:07.791231+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178027791_m2.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.098071806,"height":0.025538707},"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.8081782,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"bounds":{"left":0.8234708,"top":0.019952115,"width":0.09208777,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.007978723,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.007978723,"height":0.0},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.00731383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.006981383,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.7124335,"top":0.10055866,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.72140956,"top":0.09896249,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-5568559572385962034
|
1126372201043036670
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error...
|
56462
|
NULL
|
NULL
|
NULL
|
|
56465
|
1966
|
36
|
2026-05-19T08:07:08.668144+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-19/1779 /Users/lukas/.screenpipe/data/data/2026-05-19/1779178028668_m1.jpg...
|
PhpStorm
|
faVsco.js – AskAnythingPromptService.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JY-20676-delete-report-related-objects, menu","depth":5,"on_screen":true,"help_text":"Git Branch: JY-20676-delete-report-related-objects","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"AskJiminnyReportActivityServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'AskJiminnyReportActivityServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"4","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.016666668,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"2","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.016666668,"height":0.02111111},"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.015277778,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.014583333,"height":0.025555555},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\AskAnything;\n\nuse Jiminny\\Component\\AskAnything\\Dtos\\AskAnythingPromptDto;\nuse Jiminny\\Contracts\\Repositories\\GroupRepositoryInterface;\nuse Jiminny\\Exceptions\\InvalidArgumentException;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPrompt;\nuse Jiminny\\Models\\AskAnything\\AskAnythingPromptTarget;\nuse Jiminny\\Models\\AskAnything\\UserAskAnythingPrompt;\nuse Jiminny\\Models\\Group;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\AskAnythingRepository;\nuse Jiminny\\Repositories\\UserRepository;\n\nclass AskAnythingPromptService\n{\n public function __construct(\n private readonly AskAnythingRepository $askAnythingRepository,\n private readonly UserRepository $userRepository,\n private readonly GroupRepositoryInterface $groupRepository,\n ) {\n }\n\n /**\n * @return array<AskAnythingPromptDto>\n */\n public function get(User $user, AskAnythingPromptTarget $target): array\n {\n $prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(\n $user,\n $target\n );\n\n $promptDtos = [];\n foreach ($prompts as $prompt) {\n $ownerUuid = null;\n if ($prompt->getOwner() !== null) {\n $ownerUuid = $prompt->getOwner()->getUuid();\n }\n $shareUsers = null;\n $shareGroups = null;\n\n // Provide users and groups only if owner of the prompt is current user\n if ($prompt->getOwnerId() === $user->getId()) {\n [$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);\n }\n\n $promptDtos[] = new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $ownerUuid,\n $shareUsers,\n $shareGroups,\n $prompt->has_reports,\n );\n }\n\n return $promptDtos;\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n */\n public function create(\n User $user,\n string $title,\n string $content,\n AskAnythingPromptTarget $target,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n $prompt = $this->askAnythingRepository->createPrompt(\n $user,\n $target,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n\n return new AskAnythingPromptDto(\n $prompt->getUuid(),\n $prompt->getTitle(),\n $prompt->getContent(),\n $target,\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $prompt->has_reports,\n );\n }\n\n /**\n * @param array<string> $shareUsersUuids\n * @param array<string> $shareGroupsUuids\n *\n * @throws InvalidArgumentException\n */\n public function edit(\n AskAnythingPrompt $prompt,\n User $user,\n string $title,\n string $content,\n array $shareUsersUuids,\n array $shareGroupsUuids\n ): AskAnythingPromptDto {\n $shareUsers = $shareGroups = [];\n foreach ($shareUsersUuids as $userUuid) {\n $shareUsers[] = $this->userRepository->findByUuid($userUuid);\n }\n foreach ($shareGroupsUuids as $groupUuid) {\n $shareGroups[] = $this->groupRepository->findByUuid($groupUuid);\n }\n\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n\n $newPrompt = $this->askAnythingRepository->createPrompt(\n $user,\n $prompt->getTarget(),\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $newPrompt = $this->askAnythingRepository->editPrompt(\n $prompt,\n $title,\n $content,\n $shareUsers,\n $shareGroups,\n );\n } else {\n throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());\n }\n\n return new AskAnythingPromptDto(\n $newPrompt->getUuid(),\n $newPrompt->getTitle(),\n $newPrompt->getContent(),\n $newPrompt->getTarget(),\n $user->getUuid(),\n $shareUsersUuids,\n $shareGroupsUuids,\n $newPrompt->has_reports,\n );\n }\n\n public function delete(\n AskAnythingPrompt $prompt,\n User $user\n ): AskAnythingPrompt {\n if ($prompt->isDefaultPrompt()) {\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } elseif ($prompt->getOwnerId() === $user->getId()) {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $userPrompt?->delete();\n // For each relation, re-create the prompt for the receiver as their own\n $this->recreatePromptsForEachRelation($prompt);\n\n // Finally, delete the prompt\n $this->deletePromptIfNoRelations($prompt);\n } else {\n $userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);\n $groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);\n\n // If the prompt is shared directly with the user, then \"unshare\" it\n if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {\n $userPrompt->delete();\n $this->deletePromptIfNoRelations($prompt);\n } elseif ($groupPrompt instanceof UserAskAnythingPrompt) {\n // If the prompt is shared with the user and the group, then hide it for this user\n $this->askAnythingRepository->hidePromptForUser($prompt, $user);\n } else {\n throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());\n }\n }\n\n return $prompt;\n }\n\n public function reorder(\n User $user,\n array $promptUuids,\n ): void {\n foreach ($promptUuids as $index => $promptUuid) {\n $prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);\n $this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);\n }\n }\n\n /**\n * @param AskAnythingPrompt $prompt\n *\n * @return array[array<string>, array<string>]\n */\n private function getReceiverUuids(AskAnythingPrompt $prompt): array\n {\n $shareUsers = [];\n $shareGroups = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $shareUsers[] = $sharedUser->getUuid();\n }\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n $shareGroups[] = $sharedGroup->getUuid();\n }\n }\n\n return [$shareUsers, $shareGroups];\n }\n\n private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void\n {\n if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {\n // Disable and orphan any AutomatedReports that use this prompt\n $prompt->automatedReports()->withTrashed()->update([\n 'ask_anything_prompt_id' => null,\n 'status' => false,\n ]);\n\n // Delete only if there are no other relations to it.\n $this->askAnythingRepository->deletePrompt($prompt);\n }\n }\n\n private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void\n {\n [$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);\n $this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);\n }\n\n private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array\n {\n $sharedUsersIds = [];\n $sharedUsersRemovedIds = [];\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedUser = $sharedPrompt->getUser();\n if ($sharedPrompt->isRemoved() === true) {\n $sharedUsersRemovedIds[] = $sharedUser->getId();\n }\n if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {\n $sharedUsersIds[] = $sharedUser->getId();\n $this->askAnythingRepository->createPrompt(\n $sharedUser,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n $sharedPrompt->delete();\n }\n }\n\n return [$sharedUsersIds, $sharedUsersRemovedIds];\n }\n\n private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void\n {\n foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {\n $sharedGroup = $sharedPrompt->getGroup();\n if ($sharedGroup instanceof Group) {\n foreach ($sharedGroup->getMembers() as $member) {\n if (! in_array($member->getId(), $sharedUsersIds)\n && ! in_array($member->getId(), $sharedUsersRemovedIds)) {\n $sharedUsersIds[] = $member->getId();\n $this->askAnythingRepository->createPrompt(\n $member,\n $prompt->getTarget(),\n $prompt->getTitle(),\n $prompt->getContent(),\n [],\n [],\n );\n }\n }\n $sharedPrompt->delete();\n }\n }\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\ndeclare(strict_types=1);\n\nnamespace Jiminny\\Component\\ActivitySearch\\FilterDefinition;\n\nuse Illuminate\\Support\\Collection;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinition;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQuery;\nuse Jiminny\\Component\\ActivitySearch\\FilterDefinitionQueryCollection;\nuse Jiminny\\Contracts\\ActivitySearch\\ValidatedFilterDefinitionInterface;\nuse Jiminny\\Contracts\\Repositories\\UserRepository;\nuse Jiminny\\Models;\nuse Jiminny\\Models\\Feature\\FeatureEnum;\nuse Jiminny\\Models\\Team;\nuse Jiminny\\Traits\\RequiresUUID;\nuse Elastica\\Query;\n\nfinal class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface\n{\n private const int NO_GROUP_ID = 999;\n private UserRepository $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this->userRepository = $userRepository;\n }\n\n public function shouldApplyQueries(): bool\n {\n return count($this->getValue()) > 0;\n }\n\n public function getQueries(): FilterDefinitionQueryCollection\n {\n $userIds = $this->getValue();\n\n return FilterDefinitionQueryCollection::make([\n FilterDefinitionQuery::instance()\n ->setQuery(new Query\\Terms('coachingFeedbacks.coach.id_string', $userIds))\n ->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),\n ]);\n }\n\n public function toArray(): array\n {\n return [\n 'id' => 'coaching-feedback-user-filter',\n 'label' => 'Coach',\n 'helpText' => 'The person who completed the Coaching Framework',\n 'placeholder' => 'Search coaches',\n 'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,\n 'queryParam' => 'coaching_feedback_coach_id',\n 'options' => $this->getOptions(),\n 'groupLabelKey' => 'label',\n 'groupValuesKey' => 'users',\n 'optionLabelKey' => 'name',\n 'optionValueKey' => 'id',\n 'value' => $this->getValue(),\n ];\n }\n\n private function getOptions(): array\n {\n $user = $this->executedBy;\n $query = $user\n ->getTeam()\n ->users()\n ->whereNotIn(\n 'uuid',\n $this->userRepository->findInaccessibleDeactivatedUserUuids($user)\n ->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))\n ->all(),\n )\n ->orderBy('name');\n\n $users = $query\n ->with('group')\n ->get()\n ->reduce(\n static function (array $carry, Models\\User $user): array {\n $group = $user->getGroup();\n $groupId = $group !== null\n ? $group->getUuid()\n : self::NO_GROUP_ID;\n $groupName = $group !== null\n ? $group->getName()\n : '(NON-GROUPED)';\n\n if (! array_key_exists($groupId, $carry)) {\n $carry[$groupId] = [\n 'label' => $groupName,\n 'users' => [],\n ];\n }\n\n $carry[$groupId]['users'][] = [\n 'id' => $user->getUuid(),\n 'name' => sprintf(\n '%s%s',\n $user->getName(),\n ! $user->isStatusActive()\n ? ' (Inactive)'\n : ''\n ),\n ];\n\n return $carry;\n },\n []\n );\n\n return Collection::make($users)\n ->sortBy('label')\n ->values()\n ->toArray();\n }\n\n public function getValue(): array\n {\n if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {\n return $this->getDefaultValue();\n }\n\n return array_diff(\n $this->criteria->getCoachingFeedbackCoachUserId(),\n $this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),\n );\n }\n\n private function getDefaultValue(): array\n {\n return [];\n }\n\n public function getValidationRules(?string $prefix = null): array\n {\n $team = $this->executedBy->getTeam();\n\n return [\n $prefix . 'coaching_feedback_coach_id' => 'array',\n $prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),\n ];\n }\n\n public function getSortOrder(): int\n {\n return 86;\n }\n\n public function shouldBeIncluded(Team $team): bool\n {\n return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
395026636455006835
|
1126917008115010046
|
click
|
accessibility
|
NULL
|
Project: faVsco.js, menu
JY-20676-delete-report-re Project: faVsco.js, menu
JY-20676-delete-report-related-objects, menu
Start Listening for PHP Debug Connections
AskJiminnyReportActivityServiceTest
Run 'AskJiminnyReportActivityServiceTest'
Debug 'AskJiminnyReportActivityServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Sync Changes
Hide This Notification
Code changed:
Hide
4
2
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\AskAnything;
use Jiminny\Component\AskAnything\Dtos\AskAnythingPromptDto;
use Jiminny\Contracts\Repositories\GroupRepositoryInterface;
use Jiminny\Exceptions\InvalidArgumentException;
use Jiminny\Models\AskAnything\AskAnythingPrompt;
use Jiminny\Models\AskAnything\AskAnythingPromptTarget;
use Jiminny\Models\AskAnything\UserAskAnythingPrompt;
use Jiminny\Models\Group;
use Jiminny\Models\User;
use Jiminny\Repositories\AskAnythingRepository;
use Jiminny\Repositories\UserRepository;
class AskAnythingPromptService
{
public function __construct(
private readonly AskAnythingRepository $askAnythingRepository,
private readonly UserRepository $userRepository,
private readonly GroupRepositoryInterface $groupRepository,
) {
}
/**
* @return array<AskAnythingPromptDto>
*/
public function get(User $user, AskAnythingPromptTarget $target): array
{
$prompts = $this->askAnythingRepository->findPromptsByUserAndTarget(
$user,
$target
);
$promptDtos = [];
foreach ($prompts as $prompt) {
$ownerUuid = null;
if ($prompt->getOwner() !== null) {
$ownerUuid = $prompt->getOwner()->getUuid();
}
$shareUsers = null;
$shareGroups = null;
// Provide users and groups only if owner of the prompt is current user
if ($prompt->getOwnerId() === $user->getId()) {
[$shareUsers, $shareGroups] = $this->getReceiverUuids($prompt);
}
$promptDtos[] = new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$ownerUuid,
$shareUsers,
$shareGroups,
$prompt->has_reports,
);
}
return $promptDtos;
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*/
public function create(
User $user,
string $title,
string $content,
AskAnythingPromptTarget $target,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
$prompt = $this->askAnythingRepository->createPrompt(
$user,
$target,
$title,
$content,
$shareUsers,
$shareGroups,
);
return new AskAnythingPromptDto(
$prompt->getUuid(),
$prompt->getTitle(),
$prompt->getContent(),
$target,
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$prompt->has_reports,
);
}
/**
* @param array<string> $shareUsersUuids
* @param array<string> $shareGroupsUuids
*
* @throws InvalidArgumentException
*/
public function edit(
AskAnythingPrompt $prompt,
User $user,
string $title,
string $content,
array $shareUsersUuids,
array $shareGroupsUuids
): AskAnythingPromptDto {
$shareUsers = $shareGroups = [];
foreach ($shareUsersUuids as $userUuid) {
$shareUsers[] = $this->userRepository->findByUuid($userUuid);
}
foreach ($shareGroupsUuids as $groupUuid) {
$shareGroups[] = $this->groupRepository->findByUuid($groupUuid);
}
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
$newPrompt = $this->askAnythingRepository->createPrompt(
$user,
$prompt->getTarget(),
$title,
$content,
$shareUsers,
$shareGroups,
);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$newPrompt = $this->askAnythingRepository->editPrompt(
$prompt,
$title,
$content,
$shareUsers,
$shareGroups,
);
} else {
throw new InvalidArgumentException('Edit not allowed for prompt ' . $prompt->getUuid());
}
return new AskAnythingPromptDto(
$newPrompt->getUuid(),
$newPrompt->getTitle(),
$newPrompt->getContent(),
$newPrompt->getTarget(),
$user->getUuid(),
$shareUsersUuids,
$shareGroupsUuids,
$newPrompt->has_reports,
);
}
public function delete(
AskAnythingPrompt $prompt,
User $user
): AskAnythingPrompt {
if ($prompt->isDefaultPrompt()) {
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} elseif ($prompt->getOwnerId() === $user->getId()) {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$userPrompt?->delete();
// For each relation, re-create the prompt for the receiver as their own
$this->recreatePromptsForEachRelation($prompt);
// Finally, delete the prompt
$this->deletePromptIfNoRelations($prompt);
} else {
$userPrompt = $this->askAnythingRepository->findSharedPromptByUser($prompt->getId(), $user);
$groupPrompt = $this->askAnythingRepository->findSharedPromptByUserGroup($prompt->getId(), $user);
// If the prompt is shared directly with the user, then "unshare" it
if ($userPrompt instanceof UserAskAnythingPrompt && $groupPrompt === null) {
$userPrompt->delete();
$this->deletePromptIfNoRelations($prompt);
} elseif ($groupPrompt instanceof UserAskAnythingPrompt) {
// If the prompt is shared with the user and the group, then hide it for this user
$this->askAnythingRepository->hidePromptForUser($prompt, $user);
} else {
throw new InvalidArgumentException('Unknown delete allowance for prompt ' . $prompt->getUuid());
}
}
return $prompt;
}
public function reorder(
User $user,
array $promptUuids,
): void {
foreach ($promptUuids as $index => $promptUuid) {
$prompt = $this->askAnythingRepository->getPromptByUuid($promptUuid);
$this->askAnythingRepository->orderPromptForUser($prompt, $user, $index + 1);
}
}
/**
* @param AskAnythingPrompt $prompt
*
* @return array[array<string>, array<string>]
*/
private function getReceiverUuids(AskAnythingPrompt $prompt): array
{
$shareUsers = [];
$shareGroups = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedUser instanceof User && $sharedUser->isStatusActive()) {
$shareUsers[] = $sharedUser->getUuid();
}
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
$shareGroups[] = $sharedGroup->getUuid();
}
}
return [$shareUsers, $shareGroups];
}
private function deletePromptIfNoRelations(AskAnythingPrompt $prompt): void
{
if ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId())->isEmpty()) {
// Disable and orphan any AutomatedReports that use this prompt
$prompt->automatedReports()->withTrashed()->update([
'ask_anything_prompt_id' => null,
'status' => false,
]);
// Delete only if there are no other relations to it.
$this->askAnythingRepository->deletePrompt($prompt);
}
}
private function recreatePromptsForEachRelation(AskAnythingPrompt $prompt): void
{
[$sharedUsersIds, $sharedUsersRemovedIds] = $this->recreatePromptsForUserRelations($prompt);
$this->recreatePromptsForGroupRelations($prompt, $sharedUsersIds, $sharedUsersRemovedIds);
}
private function recreatePromptsForUserRelations(AskAnythingPrompt $prompt): array
{
$sharedUsersIds = [];
$sharedUsersRemovedIds = [];
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedUser = $sharedPrompt->getUser();
if ($sharedPrompt->isRemoved() === true) {
$sharedUsersRemovedIds[] = $sharedUser->getId();
}
if ($sharedPrompt->isRemoved() !== true && $sharedUser instanceof User && $sharedUser->isStatusActive()) {
$sharedUsersIds[] = $sharedUser->getId();
$this->askAnythingRepository->createPrompt(
$sharedUser,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
$sharedPrompt->delete();
}
}
return [$sharedUsersIds, $sharedUsersRemovedIds];
}
private function recreatePromptsForGroupRelations(AskAnythingPrompt $prompt, array $sharedUsersIds, array $sharedUsersRemovedIds): void
{
foreach ($this->askAnythingRepository->findSharedUsersAndGroupsByPromptId($prompt->getId()) as $sharedPrompt) {
$sharedGroup = $sharedPrompt->getGroup();
if ($sharedGroup instanceof Group) {
foreach ($sharedGroup->getMembers() as $member) {
if (! in_array($member->getId(), $sharedUsersIds)
&& ! in_array($member->getId(), $sharedUsersRemovedIds)) {
$sharedUsersIds[] = $member->getId();
$this->askAnythingRepository->createPrompt(
$member,
$prompt->getTarget(),
$prompt->getTitle(),
$prompt->getContent(),
[],
[],
);
}
}
$sharedPrompt->delete();
}
}
}
}
Sync Changes
Hide This Notification
Code changed:
Hide
1
Previous Highlighted Error
Next Highlighted Error
<?php
declare(strict_types=1);
namespace Jiminny\Component\ActivitySearch\FilterDefinition;
use Illuminate\Support\Collection;
use Jiminny\Component\ActivitySearch\FilterDefinition;
use Jiminny\Component\ActivitySearch\FilterDefinitionQuery;
use Jiminny\Component\ActivitySearch\FilterDefinitionQueryCollection;
use Jiminny\Contracts\ActivitySearch\ValidatedFilterDefinitionInterface;
use Jiminny\Contracts\Repositories\UserRepository;
use Jiminny\Models;
use Jiminny\Models\Feature\FeatureEnum;
use Jiminny\Models\Team;
use Jiminny\Traits\RequiresUUID;
use Elastica\Query;
final class CoachingFeedbackCoachUserIn extends FilterDefinition implements ValidatedFilterDefinitionInterface
{
private const int NO_GROUP_ID = 999;
private UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function shouldApplyQueries(): bool
{
return count($this->getValue()) > 0;
}
public function getQueries(): FilterDefinitionQueryCollection
{
$userIds = $this->getValue();
return FilterDefinitionQueryCollection::make([
FilterDefinitionQuery::instance()
->setQuery(new Query\Terms('coachingFeedbacks.coach.id_string', $userIds))
->setPath('coachingFeedbacks.coach', 'coachingFeedbacks'),
]);
}
public function toArray(): array
{
return [
'id' => 'coaching-feedback-user-filter',
'label' => 'Coach',
'helpText' => 'The person who completed the Coaching Framework',
'placeholder' => 'Search coaches',
'inputType' => InputTypeEnum::DROPDOWN_MULTIPLE,
'queryParam' => 'coaching_feedback_coach_id',
'options' => $this->getOptions(),
'groupLabelKey' => 'label',
'groupValuesKey' => 'users',
'optionLabelKey' => 'name',
'optionValueKey' => 'id',
'value' => $this->getValue(),
];
}
private function getOptions(): array
{
$user = $this->executedBy;
$query = $user
->getTeam()
->users()
->whereNotIn(
'uuid',
$this->userRepository->findInaccessibleDeactivatedUserUuids($user)
->map(static fn (string $uuid): string => RequiresUUID::toOptimized($uuid))
->all(),
)
->orderBy('name');
$users = $query
->with('group')
->get()
->reduce(
static function (array $carry, Models\User $user): array {
$group = $user->getGroup();
$groupId = $group !== null
? $group->getUuid()
: self::NO_GROUP_ID;
$groupName = $group !== null
? $group->getName()
: '(NON-GROUPED)';
if (! array_key_exists($groupId, $carry)) {
$carry[$groupId] = [
'label' => $groupName,
'users' => [],
];
}
$carry[$groupId]['users'][] = [
'id' => $user->getUuid(),
'name' => sprintf(
'%s%s',
$user->getName(),
! $user->isStatusActive()
? ' (Inactive)'
: ''
),
];
return $carry;
},
[]
);
return Collection::make($users)
->sortBy('label')
->values()
->toArray();
}
public function getValue(): array
{
if (! $this->criteria->hasCoachingFeedbackCoachUserIds()) {
return $this->getDefaultValue();
}
return array_diff(
$this->criteria->getCoachingFeedbackCoachUserId(),
$this->userRepository->findInaccessibleDeactivatedUserUuids($this->executedBy)->all(),
);
}
private function getDefaultValue(): array
{
return [];
}
public function getValidationRules(?string $prefix = null): array
{
$team = $this->executedBy->getTeam();
return [
$prefix . 'coaching_feedback_coach_id' => 'array',
$prefix . 'coaching_feedback_coach_id.*' => 'uuid:users,team_id,' . $team->getId(),
];
}
public function getSortOrder(): int
{
return 86;
}
public function shouldBeIncluded(Team $team): bool
{
return $team->hasFeature(FeatureEnum::COACHING_FRAMEWORK);
}
}
Project
Project
New File or Directory…
Expand Selected
Collapse All
Options
Hide...
|
NULL
|
NULL
|
NULL
|
NULL
|