Skip to content

Commit 64ddecc

Browse files
update tests
1 parent bc1fbb0 commit 64ddecc

24 files changed

Lines changed: 1110 additions & 0 deletions

tests/Feature/ApiResources/HasStatesResourceMethodsTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
describe('HasStates resource methods', function () {
1414
describe('getStateResource', function () {
15+
/**
16+
* Scenario: Model returns its current state as a resource array
17+
* Setup: Create post in draft state
18+
* Assertions: Resource contains all state metadata keys and correct values
19+
*/
1520
it('returns state as resource array', function () {
1621
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
1722

@@ -33,6 +38,11 @@
3338
expect($resource['is_current'])->toBeTrue();
3439
});
3540

41+
/**
42+
* Scenario: State resource respects user context for permission checks
43+
* Setup: Create admin user and draft post
44+
* Assertions: Resource generated successfully with user context
45+
*/
3646
it('accepts user context', function () {
3747
$user = new User(['id' => 1, 'role' => 'admin']);
3848
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
@@ -42,6 +52,11 @@
4252
expect($resource['name'])->toBe('draft');
4353
});
4454

55+
/**
56+
* Scenario: Resource handles models with null state gracefully
57+
* Setup: Create post and manually set state to null
58+
* Assertions: Resource returns with name key present
59+
*/
4560
it('handles null state', function () {
4661
// Create post without triggering the creating hook
4762
$post = new Post(['id' => 999, 'title' => 'No State']);
@@ -58,6 +73,11 @@
5873
});
5974

6075
describe('getStateForUI', function () {
76+
/**
77+
* Scenario: Model returns simplified state data for UI rendering
78+
* Setup: Create post in draft state
79+
* Assertions: UI data contains name, title, color, icon keys with correct values
80+
*/
6181
it('returns state for UI display', function () {
6282
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
6383

@@ -69,6 +89,11 @@
6989
expect($ui['color'])->toBe('primary');
7090
});
7191

92+
/**
93+
* Scenario: UI method returns null when model has no state
94+
* Setup: Create post and clear its state attribute
95+
* Assertions: getStateForUI returns null
96+
*/
7297
it('returns null for no state', function () {
7398
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
7499
$post->setAttribute('state', null);
@@ -80,6 +105,11 @@
80105
});
81106

82107
describe('getNextStatesForUI', function () {
108+
/**
109+
* Scenario: Model returns available transitions formatted for UI
110+
* Setup: Create post in draft state (has transitions)
111+
* Assertions: Array of next states with UI metadata (name, title, color, icon)
112+
*/
83113
it('returns next states for UI display', function () {
84114
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
85115

@@ -92,6 +122,11 @@
92122
expect($nextState)->toHaveKeys(['name', 'title', 'color', 'icon']);
93123
});
94124

125+
/**
126+
* Scenario: Next states are filtered by user permissions
127+
* Setup: Create admin user and draft post
128+
* Assertions: Next states array respects user context
129+
*/
95130
it('accepts user context', function () {
96131
$user = new User(['id' => 1, 'role' => 'admin']);
97132
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
@@ -101,6 +136,11 @@
101136
expect($nextStates)->toBeArray();
102137
});
103138

139+
/**
140+
* Scenario: Terminal states return no available transitions
141+
* Setup: Create post in published state (terminal state with no outgoing transitions)
142+
* Assertions: Empty array returned
143+
*/
104144
it('returns empty array when no transitions available', function () {
105145
// Published has no outgoing transitions
106146
$post = Post::create(['title' => 'Test', 'state' => 'published']);

tests/Feature/ApiResources/StateCollectionResourceTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
});
1616

1717
describe('StateCollectionResource', function () {
18+
/**
19+
* Scenario: Generate collection resource for all states of a model
20+
* Setup: Use Post model class with configured states
21+
* Assertions: Returns non-empty array of state resources
22+
*/
1823
it('creates collection for model class', function () {
1924
$request = Request::create('/');
2025
$resource = StateCollectionResource::forModel(Post::class);
@@ -25,6 +30,11 @@
2530
expect($array)->not->toBeEmpty();
2631
});
2732

33+
/**
34+
* Scenario: Non-stateful models return empty collection
35+
* Setup: Use User model which doesn't have state management
36+
* Assertions: Returns empty array
37+
*/
2838
it('creates empty collection for non-stateable model', function () {
2939
$request = Request::create('/');
3040
$resource = StateCollectionResource::forModel(User::class);
@@ -35,6 +45,11 @@
3545
expect($array)->toBeEmpty();
3646
});
3747

48+
/**
49+
* Scenario: Generate collection of available next states for a model instance
50+
* Setup: Create draft post with configured transitions
51+
* Assertions: Returns array with at least one next state
52+
*/
3853
it('creates collection for next states', function () {
3954
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
4055
$request = Request::create('/');
@@ -46,6 +61,11 @@
4661
expect(count($array))->toBeGreaterThan(0);
4762
});
4863

64+
/**
65+
* Scenario: Filter next states based on user permissions
66+
* Setup: Create admin user and draft post
67+
* Assertions: Collection respects user's permission context
68+
*/
4969
it('creates collection with user context', function () {
5070
$user = new User(['id' => 1, 'role' => 'admin']);
5171
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
@@ -57,6 +77,11 @@
5777
expect($array)->toBeArray();
5878
});
5979

80+
/**
81+
* Scenario: Return only essential state data to reduce API payload size
82+
* Setup: Create draft post, request next states in minimal format
83+
* Assertions: Array items contain only name and title, no color or metadata
84+
*/
6085
it('supports minimal format', function () {
6186
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
6287
$request = Request::create('/');
@@ -70,6 +95,11 @@
7095
}
7196
});
7297

98+
/**
99+
* Scenario: Return UI-optimized state data with visual metadata but without transition flags
100+
* Setup: Create draft post, request next states in UI format
101+
* Assertions: Items include name, title, color, icon, description but exclude is_current/can_transition_to
102+
*/
73103
it('supports ui format', function () {
74104
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
75105
$request = Request::create('/');
@@ -83,6 +113,11 @@
83113
}
84114
});
85115

116+
/**
117+
* Scenario: Return complete state data including all metadata and transition capabilities
118+
* Setup: Create draft post, request next states in full format
119+
* Assertions: Items contain all fields including is_default, is_current, can_transition_to
120+
*/
86121
it('supports full format', function () {
87122
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
88123
$request = Request::create('/');
@@ -102,6 +137,11 @@
102137
}
103138
});
104139

140+
/**
141+
* Scenario: Provide model context to collection so it can mark the current state correctly
142+
* Setup: Create post in draft state, build collection with Draft and Review states
143+
* Assertions: Draft state is marked as is_current=true since post is in draft
144+
*/
105145
it('sets model context with withModel', function () {
106146
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
107147
$request = Request::create('/');
@@ -116,6 +156,11 @@
116156
expect($draftItem['is_current'])->toBeTrue();
117157
});
118158

159+
/**
160+
* Scenario: Pass user context to enable permission-based filtering of available states
161+
* Setup: Create admin user and draft post, build Review state collection with user context
162+
* Assertions: Collection is successfully built with user permission context applied
163+
*/
119164
it('sets user context with withUser', function () {
120165
$user = new User(['id' => 1, 'role' => 'admin']);
121166
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
@@ -130,6 +175,11 @@
130175
expect($array)->toBeArray();
131176
});
132177

178+
/**
179+
* Scenario: Get complete list of all possible states for a given model type
180+
* Setup: Use Post model class which has draft, review, published, rejected states
181+
* Assertions: Returned array contains all configured state names for Post model
182+
*/
133183
it('returns states for model from all states', function () {
134184
$request = Request::create('/');
135185
$resource = StateCollectionResource::forModel(Post::class);

tests/Feature/ApiResources/StateResourceTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
// -----------------------------------------------------------------------------
2121

2222
describe('StateResourceData', function () {
23+
/**
24+
* Scenario: Create a data transfer object from a state class to prepare for serialization
25+
* Setup: Use Draft state class which has name, title, color, and is marked as default
26+
* Assertions: DTO properties match state class metadata including default state flag
27+
*/
2328
it('creates from state class with basic properties', function () {
2429
$data = StateResourceData::fromStateClass(Draft::class);
2530

@@ -29,6 +34,11 @@
2934
expect($data->isDefault)->toBeTrue();
3035
});
3136

37+
/**
38+
* Scenario: Serialize DTO to complete array structure for full API responses
39+
* Setup: Create DTO from Draft state
40+
* Assertions: Array includes all 9 keys: identification, visual metadata, state flags, and additional data
41+
*/
3242
it('converts to full array', function () {
3343
$data = StateResourceData::fromStateClass(Draft::class);
3444
$array = $data->toArray();
@@ -49,6 +59,11 @@
4959
expect($array['is_default'])->toBeTrue();
5060
});
5161

62+
/**
63+
* Scenario: Serialize to minimal format containing only identifier and human-readable name
64+
* Setup: Create DTO from Draft state
65+
* Assertions: Only name and title present; no visual or flag metadata to minimize payload
66+
*/
5267
it('converts to minimal array', function () {
5368
$data = StateResourceData::fromStateClass(Draft::class);
5469
$array = $data->toMinimal();
@@ -58,6 +73,11 @@
5873
expect($array)->not->toHaveKey('is_default');
5974
});
6075

76+
/**
77+
* Scenario: Serialize to UI format with visual metadata for rendering but without business logic flags
78+
* Setup: Create DTO from Draft state
79+
* Assertions: Includes UI elements (color, icon, description) but excludes is_default and is_current
80+
*/
6181
it('converts to UI array', function () {
6282
$data = StateResourceData::fromStateClass(Draft::class);
6383
$array = $data->toUI();
@@ -77,6 +97,11 @@
7797
expect($reviewData->isCurrent)->toBeFalse();
7898
});
7999

100+
/**
101+
* Scenario: Check if a state is reachable from model's current state via allowed transitions
102+
* Setup: Create draft post, generate DTOs for Draft (current) and Review (next) states
103+
* Assertions: Can't transition to current state (Draft), can transition to allowed next state (Review)
104+
*/
80105
it('detects can transition to with model context', function () {
81106
$post = Post::create(['title' => 'Test', 'state' => 'draft']);
82107

0 commit comments

Comments
 (0)