Skip to content

Commit ce53f64

Browse files
committed
My Account: Covered profile and auth pages with tests
1 parent f55e7ca commit ce53f64

File tree

3 files changed

+167
-1
lines changed

3 files changed

+167
-1
lines changed

app/Users/Controllers/UserAccountController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public function updateNotifications(Request $request)
161161
*/
162162
public function showAuth(SocialAuthService $socialAuthService)
163163
{
164-
$mfaMethods = user()->mfaValues->groupBy('method');
164+
$mfaMethods = user()->mfaValues()->get()->groupBy('method');
165165

166166
$this->setPageTitle(trans('preferences.auth'));
167167

tests/Permissions/RolePermissionsTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public function test_user_cannot_change_email_unless_they_have_manage_users_perm
4949

5050
$resp = $this->get('/my-account/profile')->assertOk();
5151
$this->withHtml($resp)->assertElementExists('input[name=email][disabled]');
52+
$resp->assertSee('Unfortunately you don\'t have permission to change your email address.');
5253
$this->put('/my-account/profile', [
5354
'name' => 'my_new_name',
5455
'email' => 'new_email@example.com',

tests/User/UserMyAccountTest.php

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
namespace Tests\User;
44

5+
use BookStack\Access\Mfa\MfaValue;
56
use BookStack\Activity\Tools\UserEntityWatchOptions;
67
use BookStack\Activity\WatchLevels;
8+
use BookStack\Api\ApiToken;
9+
use BookStack\Uploads\Image;
10+
use Illuminate\Support\Facades\Hash;
11+
use Illuminate\Support\Str;
712
use Tests\TestCase;
813

914
class UserMyAccountTest extends TestCase
@@ -26,6 +31,166 @@ public function test_views_not_accessible_to_guest_user()
2631
$resp->assertRedirect('/');
2732
}
2833
}
34+
35+
public function test_profile_updating()
36+
{
37+
$editor = $this->users->editor();
38+
39+
$resp = $this->actingAs($editor)->get('/my-account/profile');
40+
$resp->assertSee('Profile Details');
41+
42+
$html = $this->withHtml($resp);
43+
$html->assertFieldHasValue('name', $editor->name);
44+
$html->assertFieldHasValue('email', $editor->email);
45+
46+
$resp = $this->put('/my-account/profile', [
47+
'name' => 'Barryius',
48+
'email' => 'barryius@example.com',
49+
'language' => 'fr',
50+
]);
51+
52+
$resp->assertRedirect('/my-account/profile');
53+
$this->assertDatabaseHas('users', [
54+
'name' => 'Barryius',
55+
'email' => $editor->email, // No email change due to not having permissions
56+
]);
57+
$this->assertEquals(setting()->getUser($editor, 'language'), 'fr');
58+
}
59+
60+
public function test_profile_user_avatar_update_and_reset()
61+
{
62+
$user = $this->users->viewer();
63+
$avatarFile = $this->files->uploadedImage('avatar-icon.png');
64+
65+
$this->assertEquals(0, $user->image_id);
66+
67+
$upload = $this->actingAs($user)->call('PUT', "/my-account/profile", [
68+
'name' => 'Barry Scott',
69+
], [], ['profile_image' => $avatarFile], []);
70+
$upload->assertRedirect('/my-account/profile');
71+
72+
73+
$user->refresh();
74+
$this->assertNotEquals(0, $user->image_id);
75+
/** @var Image $image */
76+
$image = Image::query()->findOrFail($user->image_id);
77+
$this->assertFileExists(public_path($image->path));
78+
79+
$reset = $this->put("/my-account/profile", [
80+
'name' => 'Barry Scott',
81+
'profile_image_reset' => 'true',
82+
]);
83+
$upload->assertRedirect('/my-account/profile');
84+
85+
$user->refresh();
86+
$this->assertFileDoesNotExist(public_path($image->path));
87+
$this->assertEquals(0, $user->image_id);
88+
}
89+
90+
public function test_profile_admin_options_link_shows_if_permissions_allow()
91+
{
92+
$editor = $this->users->editor();
93+
94+
$resp = $this->actingAs($editor)->get('/my-account/profile');
95+
$resp->assertDontSee('Administrator Options');
96+
$this->withHtml($resp)->assertLinkNotExists(url("/settings/users/{$editor->id}"));
97+
98+
$this->permissions->grantUserRolePermissions($editor, ['users-manage']);
99+
100+
$resp = $this->actingAs($editor)->get('/my-account/profile');
101+
$resp->assertSee('Administrator Options');
102+
$this->withHtml($resp)->assertLinkExists(url("/settings/users/{$editor->id}"));
103+
}
104+
105+
public function test_profile_self_delete()
106+
{
107+
$editor = $this->users->editor();
108+
109+
$resp = $this->actingAs($editor)->get('/my-account/profile');
110+
$this->withHtml($resp)->assertLinkExists(url('/my-account/delete'), 'Delete Account');
111+
112+
$resp = $this->get('/my-account/delete');
113+
$resp->assertSee('Delete My Account');
114+
$this->withHtml($resp)->assertElementContains('form[action$="/my-account"] button', 'Confirm');
115+
116+
$resp = $this->delete('/my-account');
117+
$resp->assertRedirect('/');
118+
119+
$this->assertDatabaseMissing('users', ['id' => $editor->id]);
120+
}
121+
122+
public function test_profile_self_delete_shows_ownership_migration_if_can_manage_users()
123+
{
124+
$editor = $this->users->editor();
125+
126+
$resp = $this->actingAs($editor)->get('/my-account/delete');
127+
$resp->assertDontSee('Migrate Ownership');
128+
129+
$this->permissions->grantUserRolePermissions($editor, ['users-manage']);
130+
131+
$resp = $this->actingAs($editor)->get('/my-account/delete');
132+
$resp->assertSee('Migrate Ownership');
133+
}
134+
135+
public function test_auth_password_change()
136+
{
137+
$editor = $this->users->editor();
138+
139+
$resp = $this->actingAs($editor)->get('/my-account/auth');
140+
$resp->assertSee('Change Password');
141+
$this->withHtml($resp)->assertElementExists('form[action$="/my-account/auth/password"]');
142+
143+
$password = Str::random();
144+
$resp = $this->put('/my-account/auth/password', [
145+
'password' => $password,
146+
'password-confirm' => $password,
147+
]);
148+
$resp->assertRedirect('/my-account/auth');
149+
150+
$editor->refresh();
151+
$this->assertTrue(Hash::check($password, $editor->password));
152+
}
153+
154+
public function test_auth_password_change_hides_if_not_using_email_auth()
155+
{
156+
$editor = $this->users->editor();
157+
158+
$resp = $this->actingAs($editor)->get('/my-account/auth');
159+
$resp->assertSee('Change Password');
160+
161+
config()->set('auth.method', 'oidc');
162+
163+
$resp = $this->actingAs($editor)->get('/my-account/auth');
164+
$resp->assertDontSee('Change Password');
165+
}
166+
167+
public function test_auth_page_has_mfa_links()
168+
{
169+
$editor = $this->users->editor();
170+
$resp = $this->actingAs($editor)->get('/my-account/auth');
171+
$resp->assertSee('0 methods configured');
172+
$this->withHtml($resp)->assertLinkExists(url('/mfa/setup'));
173+
174+
MfaValue::upsertWithValue($editor, 'totp', 'testval');
175+
176+
$resp = $this->get('/my-account/auth');
177+
$resp->assertSee('1 method configured');
178+
}
179+
180+
public function test_auth_page_api_tokens()
181+
{
182+
$editor = $this->users->editor();
183+
$resp = $this->actingAs($editor)->get('/my-account/auth');
184+
$resp->assertSee('API Tokens');
185+
$this->withHtml($resp)->assertLinkExists(url("/api-tokens/{$editor->id}/create?context=my-account"));
186+
187+
ApiToken::factory()->create(['user_id' => $editor->id, 'name' => 'My great token']);
188+
$editor->unsetRelations();
189+
190+
$resp = $this->get('/my-account/auth');
191+
$resp->assertSee('My great token');
192+
}
193+
29194
public function test_interface_shortcuts_updating()
30195
{
31196
$this->asEditor();

0 commit comments

Comments
 (0)