Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,22 @@
<?php
/**
* @file
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
* upgrade path of https://www.drupal.org/node/2587275.
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Replace the user.mail configuration because the dump contains the right token
// already.
$connection->delete('config')->condition('name', 'user.mail')->execute();
$connection->insert('config')
->fields(array('collection', 'name', 'data'))
->values(array(
'collection' => '',
'name' => 'user.mail',
'data' => "a:10:{s:14:\"cancel_confirm\";a:2:{s:4:\"body\";s:369:\"[user:name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n-- [site:name] team\";s:7:\"subject\";s:59:\"Account cancellation request for [user:name] at [site:name]\";}s:14:\"password_reset\";a:2:{s:4:\"body\";s:397:\"[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n-- [site:name] team\";s:7:\"subject\";s:60:\"Replacement login information for [user:name] at [site:name]\";}s:22:\"register_admin_created\";a:2:{s:4:\"body\";s:463:\"[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:58:\"An administrator created an account for you at [site:name]\";}s:29:\"register_no_approval_required\";a:2:{s:4:\"body\";s:437:\"[user:name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:46:\"Account details for [user:name] at [site:name]\";}s:25:\"register_pending_approval\";a:2:{s:4:\"body\";s:281:\"[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:31:\"register_pending_approval_admin\";a:2:{s:4:\"body\";s:56:\"[user:name] has applied for an account.\n\n[user:edit-url]\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:16:\"status_activated\";a:2:{s:4:\"body\";s:446:\"[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (approved)\";}s:14:\"status_blocked\";a:2:{s:4:\"body\";s:89:\"[user:name],\n\nYour account on [site:account-name] has been blocked.\n\n-- [site:name] team\";s:7:\"subject\";s:56:\"Account details for [user:name] at [site:name] (blocked)\";}s:15:\"status_canceled\";a:2:{s:4:\"body\";s:82:\"[user:name],\n\nYour account on [site:name] has been canceled.\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (canceled)\";}s:8:\"langcode\";s:2:\"en\";}"
))->execute();

View file

@ -0,0 +1,6 @@
name: 'User access tests'
type: module
description: 'Support module for user access testing.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,24 @@
<?php
/**
* @file
* Dummy module implementing hook_user_access() to test if entity access is respected.
*/
use Drupal\Core\Access\AccessResult;
use Drupal\user\Entity\User;
/**
* Implements hook_ENTITY_TYPE_access() for entity type "user".
*/
function user_access_test_user_access(User $entity, $operation, $account) {
if ($entity->getUsername() == "no_edit" && $operation == "update") {
// Deny edit access.
return AccessResult::forbidden();
}
if ($entity->getUsername() == "no_delete" && $operation == "delete") {
// Deny delete access.
return AccessResult::forbidden();
}
return AccessResult::neutral();
}

View file

@ -0,0 +1,6 @@
name: 'User custom phpass params test'
type: module
description: 'Support module for testing custom phpass password algorithm parameters.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,4 @@
services:
password:
class: Drupal\Core\Password\PhpassHashedPassword
arguments: [19]

View file

@ -0,0 +1,6 @@
name: 'User module form tests'
type: module
description: 'Support module for user form testing.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,14 @@
<?php
/**
* @file
* Support module for user form testing.
*/
/**
* Implements hook_form_FORM_ID_alter() for user_cancel_form().
*/
function user_form_test_form_user_cancel_form_alter(&$form, &$form_state) {
$form['user_cancel_confirm']['#default_value'] = FALSE;
$form['access']['#value'] = \Drupal::currentUser()->hasPermission('cancel other accounts');
}

View file

@ -0,0 +1,2 @@
cancel other accounts:
title: 'Cancel other user accounts'

View file

@ -0,0 +1,7 @@
user_form_test.cancel:
path: '/user_form_test_cancel/{user}'
defaults:
_entity_form: 'user.cancel'
requirements:
_permission: 'cancel other accounts'

View file

@ -0,0 +1,6 @@
name: 'User module hooks tests'
type: module
description: 'Support module for user hooks testing.'
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,22 @@
<?php
/**
* @file
* Support module for user hooks testing.
*/
use Drupal\Component\Utility\SafeMarkup;
/**
* Implements hook_user_format_name_alter().
*/
function user_hooks_test_user_format_name_alter(&$name, $account) {
if (\Drupal::state()->get('user_hooks_test_user_format_name_alter', FALSE)) {
if (\Drupal::state()->get('user_hooks_test_user_format_name_alter_safe', FALSE)) {
$name = SafeMarkup::format('<em>@uid</em>', array('@uid' => $account->id()));
}
else {
$name = '<em>' . $account->id() . '</em>';
}
}
}

View file

@ -0,0 +1,34 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_access_perm
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: perm
options:
perm: 'views_test_data test permission'
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,45 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_access_role
label: ''
module: views
description: ''
tag: ''
base_table: views_test_data
base_field: nid
core: '8'
display:
default:
display_options:
fields:
id:
id: id
field: id
table: views_test_data
plugin_id: numeric
access:
type: role
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0
page_1:
display_options:
path: test-role
display_plugin: page
display_title: Page
id: page_1
position: 1

View file

@ -0,0 +1,139 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_field_permission
label: null
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: none
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
fields:
uid:
id: uid
table: users_field_data
field: uid
relationship: none
group_type: group
admin_label: ''
label: Uid
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
plugin_id: field
entity_type: user
entity_field: uid
permission:
id: permission
table: user__roles
field: permission
relationship: none
group_type: group
admin_label: ''
label: Permission
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
type: separator
separator: ', '
plugin_id: user_permissions
filters: { }
sorts: { }

View file

@ -0,0 +1,119 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_filter_current_user
label: Users
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
cache:
type: tag
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
exposed_form:
type: basic
options:
submit_button: Filter
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: none
options:
offset: 0
style:
type: default
options:
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
separator: ''
hide_empty: false
default_field_elements: true
fields:
uid:
id: uid
table: users
field: uid
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
filters:
uid_current:
id: uid_current
table: users
field: uid_current
relationship: none
group_type: group
admin_label: ''
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: user
plugin_id: user_current
sorts: { }
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- user
tags: { }

View file

@ -0,0 +1,142 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_filter_permission
label: null
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: none
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
fields:
uid:
id: uid
table: users
field: uid
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
link_to_user: false
plugin_id: user
entity_type: user
entity_field: uid
filters:
permission:
id: permission
table: user__roles
field: permission
relationship: none
group_type: group
admin_label: ''
operator: or
value:
'access user profiles': 'access user profiles'
group: 1
exposed: false
expose:
operator_id: '0'
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
reduce: false
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
reduce_duplicates: true
plugin_id: user_permissions
sorts:
uid:
id: uid
table: users_field_data
field: uid
relationship: none
group_type: group
admin_label: ''
order: ASC
exposed: false
expose:
label: ''
plugin_id: standard
entity_type: user
entity_field: uid

View file

@ -0,0 +1,93 @@
langcode: en
status: true
dependencies:
module:
- node
- user
id: test_groupwise_user
label: test_groupwise_user
module: views
description: ''
tag: default
base_table: users_field_data
base_field: uid
core: 8.0-dev
display:
default:
display_options:
access:
options:
perm: 'access user profiles'
type: perm
cache:
type: tag
exposed_form:
type: basic
fields:
name:
field: name
id: name
table: users_field_data
plugin_id: field
type: user_name
entity_type: user
entity_field: name
nid:
field: nid
id: nid
relationship: uid_representative
table: node_field_data
plugin_id: node
entity_type: node
entity_field: nid
filters:
status:
expose:
operator: '0'
field: status
group: 1
id: status
table: users_field_data
value: '1'
plugin_id: boolean
entity_type: user
entity_field: status
pager:
options:
items_per_page: 10
type: full
query:
type: views_query
relationships:
uid_representative:
admin_label: 'Representative node'
field: uid_representative
group_type: group
id: uid_representative
relationship: none
required: false
subquery_namespace: ''
subquery_order: DESC
subquery_regenerate: true
subquery_sort: node.nid
subquery_view: ''
table: users_field_data
plugin_id: groupwise_max
row:
type: fields
sorts:
created:
field: uid
id: uid
order: ASC
table: users_field_data
plugin_id: field
entity_type: user
entity_field: uid
style:
type: default
title: test_groupwise_user
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,63 @@
langcode: en
status: true
dependencies:
module:
- node
id: test_plugin_argument_default_current_user
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
arguments:
'null':
default_action: default
default_argument_type: current_user
field: 'null'
id: 'null'
must_not_be: false
table: views
plugin_id: 'null'
cache:
type: tag
exposed_form:
type: basic
fields:
title:
alter:
alter_text: false
ellipsis: true
html: false
make_link: false
strip_tags: false
trim: false
word_boundary: true
empty_zero: false
field: title
hide_empty: false
id: title
table: node_field_data
plugin_id: field
entity_type: node
entity_field: title
pager:
options:
id: 0
items_per_page: 10
offset: 0
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,65 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_bulk_form
label: ''
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
style:
type: table
row:
type: fields
fields:
user_bulk_form:
id: user_bulk_form
table: users
field: user_bulk_form
plugin_id: user_bulk_form
entity_type: user
name:
id: name
table: users_field_data
field: name
plugin_id: field
type: user_name
entity_type: user
entity_field: name
sorts:
uid:
id: uid
table: users_field_data
field: uid
order: ASC
plugin_id: user
entity_type: user
entity_field: uid
filters:
status:
id: status
table: users_field_data
field: status
operator: '='
value: '1'
plugin_id: boolean
entity_type: user
entity_field: status
page_1:
display_plugin: page
id: page_1
display_title: Page
position: null
display_options:
path: test-user-bulk-form

View file

@ -0,0 +1,243 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_bulk_form_combine_filter
label: test_user_bulk_form_combine_filter
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous: ' Previous'
next: 'Next '
first: '« First'
last: 'Last »'
quantity: 9
style:
type: default
row:
type: fields
fields:
user_bulk_form:
id: user_bulk_form
table: users
field: user_bulk_form
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
action_title: 'With selection'
include_exclude: exclude
selected_actions: { }
entity_type: user
plugin_id: user_bulk_form
name:
id: name
table: users_field_data
field: name
entity_type: user
entity_field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
plugin_id: field
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
type: user_name
settings: { }
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
filters:
combine:
id: combine
table: views
field: combine
relationship: none
group_type: group
admin_label: ''
operator: contains
value: dummy
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
fields:
user_bulk_form: user_bulk_form
name: name
plugin_id: combine
sorts: { }
title: test_user_bulk_form_combine_filter
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
filter_groups:
operator: AND
groups:
1: AND
cache_metadata:
max-age: 0
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
tags: { }
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
display_extenders: { }
path: test-user-bulk-form-combine-filter
cache_metadata:
max-age: 0
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
tags: { }

View file

@ -0,0 +1,60 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_changed
label: ''
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
row:
type: fields
style:
type: default
fields:
name:
id: uid
table: users_field_data
field: uid
entity_type: user
entity_field: uid
changed:
id: changed
table: users_field_data
field: changed
label: 'Updated date'
plugin_id: field
type: timestamp
settings:
date_format: html_date
custom_date_format: ''
timezone: ''
entity_type: user
entity_field: changed
filters: { }
display_plugin: default
display_title: Master
id: default
position: 0
page_1:
display_options:
path: test_user_changed
display_plugin: page
display_title: Page
id: page_1
position: 0

View file

@ -0,0 +1,131 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_data
label: test_user_data
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: perm
options:
perm: 'access user profiles'
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
fields:
name:
id: name
table: users_field_data
field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
plugin_id: field
type: user_name
entity_type: user
entity_field: name
data:
id: data
table: users
field: data
relationship: none
group_type: group
admin_label: ''
label: Data
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
data_module: views_test_config
data_name: test_value_name
plugin_id: user_data
entity_type: user
filters:
uid:
value:
value: '2'
table: users_field_data
field: uid
id: uid
expose:
operator: '0'
group: 1
plugin_id: numeric
entity_type: user
entity_field: uid
sorts:
created:
id: created
table: users_field_data
field: created
order: DESC
plugin_id: date
entity_type: user
entity_field: created

View file

@ -0,0 +1,62 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_name
label: ''
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
row:
type: fields
style:
type: default
fields:
name:
id: uid
table: users_field_data
field: uid
entity_type: user
entity_field: uid
filters:
uid:
id: uid
table: users_field_data
field: uid
exposed: true
expose:
operator_id: uid_op
label: Name
operator: uid_op
identifier: uid
remember_roles:
authenticated: authenticated
anonymous: '0'
entity_type: user
entity_field: uid
display_plugin: default
display_title: Master
id: default
position: 0
page_1:
display_options:
path: test_user_name
display_plugin: page
display_title: Page
id: page_1
position: 0

View file

@ -0,0 +1,115 @@
langcode: en
status: true
dependencies:
module:
- node
- user
id: test_user_relationship
label: test_user_relationship
module: views
description: ''
tag: default
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: perm
cache:
type: tag
exposed_form:
type: basic
fields:
name:
alter:
absolute: false
alter_text: false
ellipsis: true
external: false
html: false
make_link: false
nl2br: false
replace_spaces: false
strip_tags: false
trim: false
trim_whitespace: false
word_boundary: true
element_default_classes: true
element_label_colon: true
empty_zero: false
field: name
hide_alter_empty: false
hide_empty: false
id: name
table: users_field_data
plugin_id: field
type: user_name
entity_type: user
entity_field: name
title:
alter:
absolute: false
alter_text: false
ellipsis: false
html: false
make_link: false
strip_tags: false
trim: false
word_boundary: false
empty_zero: false
field: title
hide_empty: false
id: title
label: ''
table: node_field_data
plugin_id: field
entity_type: node
entity_field: title
uid:
alter:
absolute: false
alter_text: false
ellipsis: true
external: false
html: false
make_link: false
nl2br: false
replace_spaces: false
strip_tags: false
trim: false
trim_whitespace: false
word_boundary: true
element_default_classes: true
element_label_colon: true
empty_zero: false
field: uid
hide_alter_empty: false
hide_empty: false
id: uid
table: users_field_data
plugin_id: field
type: user
entity_type: user
entity_field: uid
pager:
options:
items_per_page: 10
type: full
query:
options:
query_comment: ''
type: views_query
title: test_user_relationship
style:
type: default
row:
type: fields
options:
default_field_elements: true
hide_empty: false
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,220 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_roles_rid
label: test_user_roles_rid
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous: ' Previous'
next: 'Next '
first: '« First'
last: 'Last »'
quantity: 9
style:
type: default
options:
grouping: { }
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
inline: { }
separator: ''
hide_empty: false
default_field_elements: true
fields:
name:
id: name
table: users_field_data
field: name
entity_type: user
entity_field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
plugin_id: field
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
type: user_name
settings: { }
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
filters:
status:
value: '1'
table: users_field_data
field: status
plugin_id: boolean
entity_type: user
entity_field: status
id: status
expose:
operator: ''
group: 1
sorts:
uid:
id: uid
table: users
field: uid
relationship: none
group_type: group
admin_label: ''
order: ASC
exposed: false
expose:
label: ''
entity_type: user
entity_field: uid
plugin_id: standard
header: { }
footer: { }
empty: { }
relationships: { }
arguments:
roles_target_id:
id: roles_target_id
table: user__roles
field: roles_target_id
relationship: none
group_type: group
admin_label: ''
default_action: empty
exception:
value: all
title_enable: false
title: All
title_enable: true
title: '{{ arguments.roles_target_id }}'
default_argument_type: fixed
default_argument_options:
argument: ''
default_argument_skip_url: false
summary_options:
base_path: ''
count: true
items_per_page: 25
override: false
summary:
sort_order: asc
number_of_records: 0
format: default_summary
specify_validation: false
validate:
type: none
fail: 'not found'
validate_options: { }
break_phrase: false
add_table: false
require_value: false
reduce_duplicates: false
plugin_id: user__roles_rid
display_extenders: { }
cache_metadata:
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args
- user.permissions
cacheable: false
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
display_extenders: { }
path: user_roles_rid_test
cache_metadata:
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args
- user.permissions
cacheable: false

View file

@ -0,0 +1,38 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_uid_argument
label: null
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
fields:
uid:
id: uid
table: users_field_data
field: uid
plugin_id: user
entity_type: user
entity_field: uid
arguments:
uid:
id: uid
table: users_field_data
field: uid
title_enable: true
title: '{{ arguments.uid }}'
plugin_id: user_uid
entity_type: user
entity_field: uid
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,40 @@
langcode: en
status: true
dependencies: { }
id: test_view_argument_validate_user
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
arguments:
'null':
default_argument_type: fixed
field: 'null'
id: 'null'
must_not_be: false
table: views
validate:
type: 'entity:user'
plugin_id: 'null'
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,40 @@
langcode: en
status: true
dependencies: { }
id: test_view_argument_validate_username
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
arguments:
'null':
default_argument_type: fixed
field: 'null'
id: 'null'
must_not_be: false
table: views
validate:
type: user_name
plugin_id: 'null'
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,177 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_views_handler_field_role
label: test_views_handler_field_role
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: perm
options:
perm: 'access user profiles'
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: none
options:
items_per_page: null
style:
type: default
row:
type: fields
fields:
name:
id: name
table: users_field_data
field: name
relationship: none
group_type: group
admin_label: ''
label: Name
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
plugin_id: field
type: user_name
entity_type: user
entity_field: name
roles_target_id:
id: roles_target_id
table: user__roles
field: roles_target_id
relationship: none
group_type: group
admin_label: ''
label: Roles
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
type: separator
separator: ''
plugin_id: user_roles
filters:
status:
value: '1'
table: users_field_data
field: status
id: status
expose:
operator: '0'
group: 1
plugin_id: boolean
entity_type: user
entity_field: status
sorts:
uid:
id: uid
table: users_field_data
field: uid
relationship: none
group_type: group
admin_label: ''
order: ASC
exposed: false
expose:
label: ''
entity_type: user
entity_field: uid
plugin_id: standard
title: test_user_role
page_1:
display_plugin: page
id: page_1
display_title: Page
position: null
display_options:
path: test-views-handler-field-role

View file

@ -0,0 +1,63 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_views_handler_field_user_name
label: test_views_handler_field_user_name
module: views
description: ''
tag: default
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
cache:
type: tag
exposed_form:
type: basic
fields:
name:
alter:
absolute: false
alter_text: false
ellipsis: false
html: false
make_link: false
strip_tags: false
trim: false
word_boundary: false
empty_zero: false
field: name
hide_empty: false
id: name
label: ''
table: users_field_data
plugin_id: field
type: user_name
entity_type: user
entity_field: name
pager:
type: full
query:
options:
query_comment: ''
type: views_query
style:
type: default
row:
type: fields
sorts:
uid:
id: uid
table: users
field: uid
plugin_id: standard
display_plugin: default
display_title: Master
id: default
position: 0

View file

@ -0,0 +1,9 @@
name: 'User test views'
type: module
description: 'Provides default views for views user tests.'
package: Testing
version: VERSION
core: 8.x
dependencies:
- user
- views

View file

@ -0,0 +1,429 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Core\Flood\DatabaseBackend;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Controller\UserAuthenticationController;
use GuzzleHttp\Cookie\CookieJar;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Drupal\hal\Encoder\JsonEncoder as HALJsonEncoder;
use Symfony\Component\Serializer\Serializer;
/**
* Tests login via direct HTTP.
*
* @group user
*/
class UserLoginHttpTest extends BrowserTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['hal'];
/**
* The cookie jar.
*
* @var \GuzzleHttp\Cookie\CookieJar
*/
protected $cookies;
/**
* The serializer.
*
* @var \Symfony\Component\Serializer\Serializer
*/
protected $serializer;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->cookies = new CookieJar();
$encoders = [new JsonEncoder(), new XmlEncoder(), new HALJsonEncoder()];
$this->serializer = new Serializer([], $encoders);
}
/**
* Executes a login HTTP request.
*
* @param string $name
* The username.
* @param string $pass
* The user password.
* @param string $format
* The format to use to make the request.
*
* @return \Psr\Http\Message\ResponseInterface The HTTP response.
* The HTTP response.
*/
protected function loginRequest($name, $pass, $format = 'json') {
$user_login_url = Url::fromRoute('user.login.http')
->setRouteParameter('_format', $format)
->setAbsolute();
$request_body = [];
if (isset($name)) {
$request_body['name'] = $name;
}
if (isset($pass)) {
$request_body['pass'] = $pass;
}
$result = \Drupal::httpClient()->post($user_login_url->toString(), [
'body' => $this->serializer->encode($request_body, $format),
'headers' => [
'Accept' => "application/$format",
],
'http_errors' => FALSE,
'cookies' => $this->cookies,
]);
return $result;
}
/**
* Tests user session life cycle.
*/
public function testLogin() {
$client = \Drupal::httpClient();
foreach ([FALSE, TRUE] as $serialization_enabled_option) {
if ($serialization_enabled_option) {
/** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */
$module_installer = $this->container->get('module_installer');
$module_installer->install(['serialization']);
$formats = ['json', 'xml', 'hal_json'];
}
else {
// Without the serialization module only JSON is supported.
$formats = ['json'];
}
foreach ($formats as $format) {
// Create new user for each iteration to reset flood.
// Grant the user administer users permissions to they can see the
// 'roles' field.
$account = $this->drupalCreateUser(['administer users']);
$name = $account->getUsername();
$pass = $account->passRaw;
$login_status_url = $this->getLoginStatusUrlString($format);
$response = $client->get($login_status_url);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT);
// Flooded.
$this->config('user.flood')
->set('user_limit', 3)
->save();
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 403, 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.', $format);
// After testing the flood control we can increase the limit.
$this->config('user.flood')
->set('user_limit', 100)
->save();
$response = $this->loginRequest(NULL, NULL, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.', $format);
$response = $this->loginRequest(NULL, $pass, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.name.', $format);
$response = $this->loginRequest($name, NULL, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.pass.', $format);
// Blocked.
$account
->block()
->save();
$response = $this->loginRequest($name, $pass, $format);
$this->assertHttpResponseWithMessage($response, 400, 'The user has not been activated or is blocked.', $format);
$account
->activate()
->save();
$response = $this->loginRequest($name, 'garbage', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest('garbage', $pass, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, $pass, $format);
$this->assertEquals(200, $response->getStatusCode());
$result_data = $this->serializer->decode($response->getBody(), $format);
$this->assertEquals($name, $result_data['current_user']['name']);
$this->assertEquals($account->id(), $result_data['current_user']['uid']);
$this->assertEquals($account->getRoles(), $result_data['current_user']['roles']);
$logout_token = $result_data['logout_token'];
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN);
$response = $this->logoutRequest($format, $logout_token);
$this->assertEquals(204, $response->getStatusCode());
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT);
$this->resetFlood();
}
}
}
/**
* Gets a value for a given key from the response.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
* @param string $key
* The key for the value.
* @param string $format
* The encoded format.
*
* @return mixed
* The value for the key.
*/
protected function getResultValue(ResponseInterface $response, $key, $format) {
$decoded = $this->serializer->decode((string) $response->getBody(), $format);
if (is_array($decoded)) {
return $decoded[$key];
}
else {
return $decoded->{$key};
}
}
/**
* Resets all flood entries.
*/
protected function resetFlood() {
$this->container->get('database')->delete(DatabaseBackend::TABLE_NAME)->execute();
}
/**
* Tests the global login flood control.
*
* @see \Drupal\basic_auth\Tests\Authentication\BasicAuthTest::testGlobalLoginFloodControl
* @see \Drupal\user\Tests\UserLoginTest::testGlobalLoginFloodControl
*/
public function testGlobalLoginFloodControl() {
$this->config('user.flood')
->set('ip_limit', 2)
// Set a high per-user limit out so that it is not relevant in the test.
->set('user_limit', 4000)
->save();
$user = $this->drupalCreateUser([]);
$incorrect_user = clone $user;
$incorrect_user->passRaw .= 'incorrect';
// Try 2 failed logins.
for ($i = 0; $i < 2; $i++) {
$response = $this->loginRequest($incorrect_user->getUsername(), $incorrect_user->passRaw);
$this->assertEquals('400', $response->getStatusCode());
}
// IP limit has reached to its limit. Even valid user credentials will fail.
$response = $this->loginRequest($user->getUsername(), $user->passRaw);
$this->assertHttpResponseWithMessage($response, '403', 'Access is blocked because of IP based flood prevention.');
}
/**
* Checks a response for status code and body.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
* @param int $expected_code
* The expected status code.
* @param mixed $expected_body
* The expected response body.
*/
protected function assertHttpResponse(ResponseInterface $response, $expected_code, $expected_body) {
$this->assertEquals($expected_code, $response->getStatusCode());
$this->assertEquals($expected_body, (string) $response->getBody());
}
/**
* Checks a response for status code and message.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
* @param int $expected_code
* The expected status code.
* @param string $expected_message
* The expected message encoded in response.
* @param string $format
* The format that the response is encoded in.
*/
protected function assertHttpResponseWithMessage(ResponseInterface $response, $expected_code, $expected_message, $format = 'json') {
$this->assertEquals($expected_code, $response->getStatusCode());
$this->assertEquals($expected_message, $this->getResultValue($response, 'message', $format));
}
/**
* Test the per-user login flood control.
*
* @see \Drupal\user\Tests\UserLoginTest::testPerUserLoginFloodControl
* @see \Drupal\basic_auth\Tests\Authentication\BasicAuthTest::testPerUserLoginFloodControl
*/
public function testPerUserLoginFloodControl() {
foreach ([TRUE, FALSE] as $uid_only_setting) {
$this->config('user.flood')
// Set a high global limit out so that it is not relevant in the test.
->set('ip_limit', 4000)
->set('user_limit', 3)
->set('uid_only', $uid_only_setting)
->save();
$user1 = $this->drupalCreateUser([]);
$incorrect_user1 = clone $user1;
$incorrect_user1->passRaw .= 'incorrect';
$user2 = $this->drupalCreateUser([]);
// Try 2 failed logins.
for ($i = 0; $i < 2; $i++) {
$response = $this->loginRequest($incorrect_user1->getUsername(), $incorrect_user1->passRaw);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.');
}
// A successful login will reset the per-user flood control count.
$response = $this->loginRequest($user1->getUsername(), $user1->passRaw);
$result_data = $this->serializer->decode($response->getBody(), 'json');
$this->logoutRequest('json', $result_data['logout_token']);
// Try 3 failed logins for user 1, they will not trigger flood control.
for ($i = 0; $i < 3; $i++) {
$response = $this->loginRequest($incorrect_user1->getUsername(), $incorrect_user1->passRaw);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.');
}
// Try one successful attempt for user 2, it should not trigger any
// flood control.
$this->drupalLogin($user2);
$this->drupalLogout();
// Try one more attempt for user 1, it should be rejected, even if the
// correct password has been used.
$response = $this->loginRequest($user1->getUsername(), $user1->passRaw);
// Depending on the uid_only setting the error message will be different.
if ($uid_only_setting) {
$excepted_message = 'There have been more than 3 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.';
}
else {
$excepted_message = 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.';
}
$this->assertHttpResponseWithMessage($response, 403, $excepted_message);
}
}
/**
* Executes a logout HTTP request.
*
* @param string $format
* The format to use to make the request.
* @param string $logout_token
* The csrf token for user logout.
*
* @return \Psr\Http\Message\ResponseInterface The HTTP response.
* The HTTP response.
*/
protected function logoutRequest($format = 'json', $logout_token = '') {
/** @var \GuzzleHttp\Client $client */
$client = $this->container->get('http_client');
$user_logout_url = Url::fromRoute('user.logout.http')
->setRouteParameter('_format', $format)
->setAbsolute();
if ($logout_token) {
$user_logout_url->setOption('query', ['token' => $logout_token]);
}
$post_options = [
'headers' => [
'Accept' => "application/$format",
],
'http_errors' => FALSE,
'cookies' => $this->cookies,
];
$response = $client->post($user_logout_url->toString(), $post_options);
return $response;
}
/**
* Test csrf protection of User Logout route.
*/
public function testLogoutCsrfProtection() {
$client = \Drupal::httpClient();
$login_status_url = $this->getLoginStatusUrlString();
$account = $this->drupalCreateUser();
$name = $account->getUsername();
$pass = $account->passRaw;
$response = $this->loginRequest($name, $pass);
$this->assertEquals(200, $response->getStatusCode());
$result_data = $this->serializer->decode($response->getBody(), 'json');
$logout_token = $result_data['logout_token'];
// Test third party site posting to current site with logout request.
// This should not logout the current user because it lacks the CSRF
// token.
$response = $this->logoutRequest('json');
$this->assertEquals(403, $response->getStatusCode());
// Ensure still logged in.
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN);
// Try with an incorrect token.
$response = $this->logoutRequest('json', 'not-the-correct-token');
$this->assertEquals(403, $response->getStatusCode());
// Ensure still logged in.
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN);
// Try a logout request with correct token.
$response = $this->logoutRequest('json', $logout_token);
$this->assertEquals(204, $response->getStatusCode());
// Ensure actually logged out.
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT);
}
/**
* Gets the URL string for checking login.
*
* @param string $format
* The format to use to make the request.
*
* @return string
* The URL string.
*/
protected function getLoginStatusUrlString($format = 'json') {
$user_login_status_url = Url::fromRoute('user.login_status.http');
$user_login_status_url->setRouteParameter('_format', $format);
$user_login_status_url->setAbsolute();
return $user_login_status_url->toString();
}
}

View file

@ -0,0 +1,157 @@
<?php
namespace Drupal\Tests\user\Kernel\Condition;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
/**
* Tests the user role condition.
*
* @group user
*/
class UserRoleConditionTest extends KernelTestBase {
/**
* The condition plugin manager.
*
* @var \Drupal\Core\Condition\ConditionManager
*/
protected $manager;
/**
* An anonymous user for testing purposes.
*
* @var \Drupal\user\UserInterface
*/
protected $anonymous;
/**
* An authenticated user for testing purposes.
*
* @var \Drupal\user\UserInterface
*/
protected $authenticated;
/**
* A custom role for testing purposes.
*
* @var \Drupal\user\Entity\RoleInterface
*/
protected $role;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user', 'field');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installSchema('system', 'sequences');
$this->installEntitySchema('user');
$this->manager = $this->container->get('plugin.manager.condition');
// Set up the authenticated and anonymous roles.
Role::create(array(
'id' => RoleInterface::ANONYMOUS_ID,
'label' => 'Anonymous user',
))->save();
Role::create(array(
'id' => RoleInterface::AUTHENTICATED_ID,
'label' => 'Authenticated user',
))->save();
// Create new role.
$rid = strtolower($this->randomMachineName(8));
$label = $this->randomString(8);
$role = Role::create(array(
'id' => $rid,
'label' => $label,
));
$role->save();
$this->role = $role;
// Setup an anonymous user for our tests.
$this->anonymous = User::create(array(
'name' => '',
'uid' => 0,
));
$this->anonymous->save();
// Loading the anonymous user adds the correct role.
$this->anonymous = User::load($this->anonymous->id());
// Setup an authenticated user for our tests.
$this->authenticated = User::create(array(
'name' => $this->randomMachineName(),
));
$this->authenticated->save();
// Add the custom role.
$this->authenticated->addRole($this->role->id());
}
/**
* Test the user_role condition.
*/
public function testConditions() {
// Grab the user role condition and configure it to check against
// authenticated user roles.
/** @var $condition \Drupal\Core\Condition\ConditionInterface */
$condition = $this->manager->createInstance('user_role')
->setConfig('roles', array(RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID))
->setContextValue('user', $this->anonymous);
$this->assertFalse($condition->execute(), 'Anonymous users fail role checks for authenticated.');
// Check for the proper summary.
// Summaries require an extra space due to negate handling in summary().
$this->assertEqual($condition->summary(), 'The user is a member of Authenticated user');
// Set the user role to anonymous.
$condition->setConfig('roles', array(RoleInterface::ANONYMOUS_ID => RoleInterface::ANONYMOUS_ID));
$this->assertTrue($condition->execute(), 'Anonymous users pass role checks for anonymous.');
// Check for the proper summary.
$this->assertEqual($condition->summary(), 'The user is a member of Anonymous user');
// Set the user role to check anonymous or authenticated.
$condition->setConfig('roles', array(RoleInterface::ANONYMOUS_ID => RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID));
$this->assertTrue($condition->execute(), 'Anonymous users pass role checks for anonymous or authenticated.');
// Check for the proper summary.
$this->assertEqual($condition->summary(), 'The user is a member of Anonymous user, Authenticated user');
// Set the context to the authenticated user and check that they also pass
// against anonymous or authenticated roles.
$condition->setContextValue('user', $this->authenticated);
$this->assertTrue($condition->execute(), 'Authenticated users pass role checks for anonymous or authenticated.');
// Set the role to just authenticated and recheck.
$condition->setConfig('roles', array(RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID));
$this->assertTrue($condition->execute(), 'Authenticated users pass role checks for authenticated.');
// Test Constructor injection.
$condition = $this->manager->createInstance('user_role', array('roles' => array(RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID), 'context' => array('user' => $this->authenticated)));
$this->assertTrue($condition->execute(), 'Constructor injection of context and configuration working as anticipated.');
// Check the negated summary.
$condition->setConfig('negate', TRUE);
$this->assertEqual($condition->summary(), 'The user is not a member of Authenticated user');
// Check the complex negated summary.
$condition->setConfig('roles', array(RoleInterface::ANONYMOUS_ID => RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID));
$this->assertEqual($condition->summary(), 'The user is not a member of Anonymous user, Authenticated user');
// Check a custom role.
$condition->setConfig('roles', array($this->role->id() => $this->role->id()));
$condition->setConfig('negate', FALSE);
$this->assertTrue($condition->execute(), 'Authenticated user is a member of the custom role.');
$this->assertEqual($condition->summary(), SafeMarkup::format('The user is a member of @roles', array('@roles' => $this->role->label())));
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace Drupal\Tests\user\Kernel\Field;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
/**
* Tests the user_name formatter.
*
* @group field
*/
class UserNameFormatterTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['field', 'user', 'system'];
/**
* @var string
*/
protected $entityType;
/**
* @var string
*/
protected $bundle;
/**
* @var string
*/
protected $fieldName;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['field']);
$this->installEntitySchema('user');
$this->installSchema('system', ['sequences']);
$this->entityType = 'user';
$this->bundle = $this->entityType;
$this->fieldName = 'name';
}
/**
* Renders fields of a given entity with a given display.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity object with attached fields to render.
* @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
* The display to render the fields in.
*
* @return string
* The rendered entity fields.
*/
protected function renderEntityFields(FieldableEntityInterface $entity, EntityViewDisplayInterface $display) {
$content = $display->build($entity);
$content = $this->render($content);
return $content;
}
/**
* Tests the formatter output.
*/
public function testFormatter() {
$user = User::create([
'name' => 'test name',
]);
$user->save();
$result = $user->{$this->fieldName}->view(['type' => 'user_name']);
$this->assertEqual('username', $result[0]['#theme']);
$this->assertEqual(spl_object_hash($user), spl_object_hash($result[0]['#account']));
$result = $user->{$this->fieldName}->view(['type' => 'user_name', 'settings' => ['link_to_entity' => FALSE]]);
$this->assertEqual($user->getDisplayName(), $result[0]['#markup']);
$user = User::getAnonymousUser();
$result = $user->{$this->fieldName}->view(['type' => 'user_name']);
$this->assertEqual('username', $result[0]['#theme']);
$this->assertEqual(spl_object_hash($user), spl_object_hash($result[0]['#account']));
$result = $user->{$this->fieldName}->view(['type' => 'user_name', 'settings' => ['link_to_entity' => FALSE]]);
$this->assertEqual($user->getDisplayName(), $result[0]['#markup']);
$this->assertEqual($this->config('user.settings')->get('anonymous'), $result[0]['#markup']);
}
}

View file

@ -0,0 +1,109 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Tests\migrate\Kernel\MigrateTestBase;
use Drupal\user\Entity\User;
/**
* Tests preservation of root account password.
*
* @group user
*/
class MigrateUserAdminPassTest extends MigrateTestBase {
/**
* The passwords as retrieved from the account entities before migration.
*
* @var array
*/
protected $originalPasswords = [];
/**
* Modules to enable.
*
* @var string[]
*/
public static $modules = ['user'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Make sure the admin user and a regular user are created.
$this->container->get('module_handler')->loadInclude('user', 'install');
$this->installEntitySchema('user');
user_install();
/** @var \Drupal\user\Entity\User $admin_account */
$admin_account = User::load(1);
$admin_account->setPassword('original');
$admin_account->save();
$this->originalPasswords[1] = $admin_account->getPassword();
/** @var \Drupal\user\Entity\User $user_account */
$user_account = User::create([
'uid' => 2,
'name' => 'original_username',
'mail' => 'original_email@example.com',
'pass' => 'original_password',
]);
$user_account->save();
$this->originalPasswords[2] = $user_account->getPassword();
}
/**
* Tests preserving the admin user's password.
*/
public function testAdminPasswordPreserved() {
$user_data_rows = [
[
'id' => '1',
'username' => 'site_admin',
'password' => 'new_password',
'email' => 'site_admin@example.com',
],
[
'id' => '2',
'username' => 'random_user',
'password' => 'random_password',
'email' => 'random_user@example.com',
],
];
$ids = ['id' => ['type' => 'integer']];
$definition = [
'id' => 'users',
'migration_tags' => ['Admin password test'],
'source' => [
'plugin' => 'embedded_data',
'data_rows' => $user_data_rows,
'ids' => $ids,
],
'process' => [
'uid' => 'id',
'name' => 'username',
'mail' => 'email',
'pass' => 'password',
],
'destination' => ['plugin' => 'entity:user'],
];
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
$this->executeMigration($migration);
// Verify that admin username and email were changed, but password was not.
/** @var \Drupal\user\Entity\User $admin_account */
$admin_account = User::load(1);
$this->assertIdentical($admin_account->getUsername(), 'site_admin');
$this->assertIdentical($admin_account->getEmail(), 'site_admin@example.com');
$this->assertIdentical($admin_account->getPassword(), $this->originalPasswords[1]);
// Verify that everything changed for the regular user.
/** @var \Drupal\user\Entity\User $user_account */
$user_account = User::load(2);
$this->assertIdentical($user_account->getUsername(), 'random_user');
$this->assertIdentical($user_account->getEmail(), 'random_user@example.com');
$this->assertNotIdentical($user_account->getPassword(), $this->originalPasswords[2]);
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* User picture entity display.
*
* @group user
*/
class MigrateUserPictureEntityDisplayTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['file', 'image'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->executeMigrations([
'user_picture_field',
'user_picture_field_instance',
'user_picture_entity_display',
]);
}
/**
* Tests the Drupal 7 user picture to Drupal 8 entity display migration.
*/
public function testUserPictureEntityDisplay() {
$component = EntityViewDisplay::load('user.user.default')->getComponent('user_picture');
$this->assertIdentical('image', $component['type']);
$this->assertIdentical('', $component['settings']['image_style']);
$this->assertIdentical('content', $component['settings']['image_link']);
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests migration of the user_picture field's entity form display settings.
*
* @group user
*/
class MigrateUserPictureEntityFormDisplayTest extends MigrateDrupal7TestBase {
public static $modules = ['image', 'file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_picture_field',
'user_picture_field_instance',
'user_picture_entity_form_display',
]);
}
/**
* Tests the field's entity form display settings.
*/
public function testEntityFormDisplaySettings() {
$component = EntityFormDisplay::load('user.user.default')->getComponent('user_picture');
$this->assertIdentical('image_image', $component['type']);
$this->assertIdentical('throbber', $component['settings']['progress_indicator']);
$this->assertIdentical('thumbnail', $component['settings']['preview_image_style']);
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Field\FieldConfigInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* User picture field instance migration.
*
* @group user
*/
class MigrateUserPictureFieldInstanceTest extends MigrateDrupal7TestBase {
public static $modules = ['image', 'file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_picture_field',
'user_picture_field_instance',
]);
}
/**
* Test the user picture field migration.
*/
public function testUserPictureField() {
/** @var \Drupal\field\FieldConfigInterface $field */
$field = FieldConfig::load('user.user.user_picture');
$this->assertTrue($field instanceof FieldConfigInterface);
$this->assertIdentical('user', $field->getTargetEntityTypeId());
$this->assertIdentical('user', $field->getTargetBundle());
$this->assertIdentical('user_picture', $field->getName());
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* User picture field migration.
*
* @group user
*/
class MigrateUserPictureFieldTest extends MigrateDrupal7TestBase {
public static $modules = ['image', 'file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('user_picture_field');
}
/**
* Test the user picture field migration.
*/
public function testUserPictureField() {
/** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
$field_storage = FieldStorageConfig::load('user.user_picture');
$this->assertTrue($field_storage instanceof FieldStorageConfigInterface);
$this->assertIdentical('user.user_picture', $field_storage->id());
$this->assertIdentical('image', $field_storage->getType());
$this->assertIdentical('user', $field_storage->getTargetEntityTypeId());
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile entity display migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileEntityDisplayTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_profile_field',
'user_profile_field_instance',
'user_profile_entity_display',
]);
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileFields() {
$display = EntityViewDisplay::load('user.user.default');
// Test a text field.
$component = $display->getComponent('profile_color');
$this->assertIdentical('text_default', $component['type']);
// Test a list field.
$component = $display->getComponent('profile_bands');
$this->assertIdentical('text_default', $component['type']);
// Test a date field.
$component = $display->getComponent('profile_birthdate');
$this->assertIdentical('datetime_default', $component['type']);
// Test PROFILE_PRIVATE field is hidden.
$this->assertNull($display->getComponent('profile_sell_address'));
// Test PROFILE_HIDDEN field is hidden.
$this->assertNull($display->getComponent('profile_sold_to'));
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile entity form display migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileEntityFormDisplayTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_profile_field',
'user_profile_field_instance',
'user_profile_entity_form_display',
]);
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileEntityFormDisplay() {
$display = EntityFormDisplay::load('user.user.default');
// Test a text field.
$component = $display->getComponent('profile_color');
$this->assertIdentical('text_textfield', $component['type']);
// Test a list field.
$component = $display->getComponent('profile_bands');
$this->assertIdentical('text_textfield', $component['type']);
// Test a date field.
$component = $display->getComponent('profile_birthdate');
$this->assertIdentical('datetime_default', $component['type']);
// Test PROFILE_PRIVATE field is hidden.
$this->assertNull($display->getComponent('profile_sell_address'));
// Test PROFILE_HIDDEN field is hidden.
$this->assertNull($display->getComponent('profile_sold_to'));
// Test that a checkbox field has the proper display label setting.
$component = $display->getComponent('profile_love_migrations');
$this->assertIdentical('boolean_checkbox', $component['type']);
$this->assertIdentical(TRUE, $component['settings']['display_label']);
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile field instance migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileFieldInstanceTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['field'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_profile_field',
'user_profile_field_instance',
]);
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileFields() {
// Migrated a text field.
$field = FieldConfig::load('user.user.profile_color');
$this->assertIdentical('Favorite color', $field->label());
$this->assertIdentical('List your favorite color', $field->getDescription());
// Migrated a textarea.
$field = FieldConfig::load('user.user.profile_biography');
$this->assertIdentical('Biography', $field->label());
$this->assertIdentical('Tell people a little bit about yourself', $field->getDescription());
// Migrated checkbox field.
$field = FieldConfig::load('user.user.profile_sell_address');
$this->assertIdentical('Sell your email address?', $field->label());
$this->assertIdentical("If you check this box, we'll sell your address to spammers to help line the pockets of our shareholders. Thanks!", $field->getDescription());
// Migrated selection field.
$field = FieldConfig::load('user.user.profile_sold_to');
$this->assertIdentical('Sales Category', $field->label());
$this->assertIdentical("Select the sales categories to which this user's address was sold.", $field->getDescription());
// Migrated list field.
$field = FieldConfig::load('user.user.profile_bands');
$this->assertIdentical('Favorite bands', $field->label());
$this->assertIdentical("Enter your favorite bands. When you've saved your profile, you'll be able to find other people with the same favorites.", $field->getDescription());
// Migrated URL field.
$field = FieldConfig::load('user.user.profile_blog');
$this->assertIdentical('Blog', $field->label());
$this->assertIdentical("Paste the full URL, including http://, of your personal blog.", $field->getDescription());
// Migrated date field.
$field = FieldConfig::load('user.user.profile_birthdate');
$this->assertIdentical('Birthdate', $field->label());
$this->assertIdentical("Enter your birth date and we'll send you a coupon.", $field->getDescription());
// Another migrated checkbox field, with a different source visibility setting.
$field = FieldConfig::load('user.user.profile_love_migrations');
$this->assertIdentical('I love migrations', $field->label());
$this->assertIdentical("If you check this box, you love migrations.", $field->getDescription());
}
}

View file

@ -0,0 +1,70 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile field migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileFieldTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('user_profile_field');
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileFields() {
// Migrated a text field.
$field_storage = FieldStorageConfig::load('user.profile_color');
$this->assertIdentical('text', $field_storage->getType(), 'Field type is text.');
$this->assertIdentical(1, $field_storage->getCardinality(), 'Text field has correct cardinality');
// Migrated a textarea.
$field_storage = FieldStorageConfig::load('user.profile_biography');
$this->assertIdentical('text_long', $field_storage->getType(), 'Field type is text_long.');
// Migrated checkbox field.
$field_storage = FieldStorageConfig::load('user.profile_sell_address');
$this->assertIdentical('boolean', $field_storage->getType(), 'Field type is boolean.');
// Migrated selection field.
$field_storage = FieldStorageConfig::load('user.profile_sold_to');
$this->assertIdentical('list_string', $field_storage->getType(), 'Field type is list_string.');
$settings = $field_storage->getSettings();
$this->assertEqual($settings['allowed_values'], array(
'Pill spammers' => 'Pill spammers',
'Fitness spammers' => 'Fitness spammers',
'Back\slash' => 'Back\slash',
'Forward/slash' => 'Forward/slash',
'Dot.in.the.middle' => 'Dot.in.the.middle',
'Faithful servant' => 'Faithful servant',
'Anonymous donor' => 'Anonymous donor',
));
$this->assertIdentical('list_string', $field_storage->getType(), 'Field type is list_string.');
// Migrated list field.
$field_storage = FieldStorageConfig::load('user.profile_bands');
$this->assertIdentical('text', $field_storage->getType(), 'Field type is text.');
$this->assertIdentical(-1, $field_storage->getCardinality(), 'List field has correct cardinality');
// Migrated URL field.
$field_storage = FieldStorageConfig::load('user.profile_blog');
$this->assertIdentical('link', $field_storage->getType(), 'Field type is link.');
// Migrated date field.
$field_storage = FieldStorageConfig::load('user.profile_birthdate');
$this->assertIdentical('datetime', $field_storage->getType(), 'Field type is datetime.');
$this->assertIdentical('date', $field_storage->getSettings()['datetime_type']);
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
use Drupal\migrate_drupal\Tests\StubTestTrait;
/**
* Test stub creation for user entities.
*
* @group user
*/
class MigrateUserStubTest extends MigrateDrupalTestBase {
use StubTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['user'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installSchema('system', ['sequences']);
}
/**
* Tests creation of user stubs.
*/
public function testStub() {
$this->performStubTest('user');
}
}

View file

@ -0,0 +1,89 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\user\AccountSettingsForm;
use Drupal\Core\Database\Database;
/**
* Upgrade variables to user.*.yml.
*
* @group migrate_drupal_6
*/
class MigrateUserConfigsTest extends MigrateDrupal6TestBase {
use SchemaCheckTestTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container->get('router.builder')->rebuild();
$this->executeMigrations(['d6_user_mail', 'd6_user_settings']);
}
/**
* Tests migration of user variables to user.mail.yml.
*/
public function testUserMail() {
$config = $this->config('user.mail');
$this->assertIdentical('Account details for [user:name] at [site:name] (approved)', $config->get('status_activated.subject'));
$this->assertIdentical("[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.\n\nOnce you have set your own password, you will be able to log in to [site:login-url] in the future using:\n\nusername: [user:name]\n", $config->get('status_activated.body'));
$this->assertIdentical('Replacement login information for [user:name] at [site:name]', $config->get('password_reset.subject'));
$this->assertIdentical("[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in to [site:url-brief] by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.", $config->get('password_reset.body'));
$this->assertIdentical('Account details for [user:name] at [site:name] (deleted)', $config->get('cancel_confirm.subject'));
$this->assertIdentical("[user:name],\n\nYour account on [site:name] has been deleted.", $config->get('cancel_confirm.body'));
$this->assertIdentical('An administrator created an account for you at [site:name]', $config->get('register_admin_created.subject'));
$this->assertIdentical("[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in to [site:login-url] using the following username and password:\n\nusername: [user:name]\npassword: \n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.\n\n\n-- [site:name] team", $config->get('register_admin_created.body'));
$this->assertIdentical('Account details for [user:name] at [site:name]', $config->get('register_no_approval_required.subject'));
$this->assertIdentical("[user:name],\n\nThank you for registering at [site:name]. You may now log in to [site:login-url] using the following username and password:\n\nusername: [user:name]\npassword: \n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.\n\n\n-- [site:name] team", $config->get('register_no_approval_required.body'));
$this->assertIdentical('Account details for [user:name] at [site:name] (pending admin approval)', $config->get('register_pending_approval.subject'));
$this->assertIdentical("[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team", $config->get('register_pending_approval.body'));
$this->assertIdentical('Account details for [user:name] at [site:name] (blocked)', $config->get('status_blocked.subject'));
$this->assertIdentical("[user:name],\n\nYour account on [site:name] has been blocked.", $config->get('status_blocked.body'));
$this->assertConfigSchema(\Drupal::service('config.typed'), 'user.mail', $config->get());
}
/**
* Tests migration of user variables to user.settings.yml.
*/
public function testUserSettings() {
$config = $this->config('user.settings');
$this->assertIdentical(TRUE, $config->get('notify.status_blocked'));
$this->assertIdentical(FALSE, $config->get('notify.status_activated'));
$this->assertIdentical(FALSE, $config->get('verify_mail'));
$this->assertIdentical('admin_only', $config->get('register'));
$this->assertIdentical('Guest', $config->get('anonymous'));
// Tests migration of user_register using the AccountSettingsForm.
// Map D6 value to D8 value
$user_register_map = [
[0, USER_REGISTER_ADMINISTRATORS_ONLY],
[1, USER_REGISTER_VISITORS],
[2, USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL],
];
foreach ($user_register_map as $map) {
// Tests migration of user_register = 1
Database::getConnection('default', 'migrate')
->update('variable')
->fields(['value' => serialize($map[0])])
->condition('name', 'user_register')
->execute();
/** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
$migration = $this->getMigration('d6_user_settings');
// Indicate we're rerunning a migration that's already run.
$migration->getIdMap()->prepareUpdate();
$this->executeMigration($migration);
$form = $this->container->get('form_builder')->getForm(AccountSettingsForm::create($this->container));
$this->assertIdentical($map[1], $form['registration_cancellation']['user_register']['#value']);
}
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Users contact settings migration.
*
* @group migrate_drupal_6
*/
class MigrateUserContactSettingsTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['contact'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->migrateUsers(FALSE);
$this->installSchema('user', ['users_data']);
$this->executeMigration('d6_user_contact_settings');
}
/**
* Tests the Drupal6 user contact settings migration.
*/
public function testUserContactSettings() {
$user_data = \Drupal::service('user.data');
$module = $key = 'contact';
$uid = 2;
$setting = $user_data->get($module, $uid, $key);
$this->assertIdentical('1', $setting);
$uid = 8;
$setting = $user_data->get($module, $uid, $key);
$this->assertIdentical('0', $setting);
$uid = 15;
$setting = $user_data->get($module, $uid, $key);
$this->assertIdentical(NULL, $setting);
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\file\Entity\File;
use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* User pictures migration.
*
* @group migrate_drupal_6
*/
class MigrateUserPictureFileTest extends MigrateDrupal6TestBase {
use FileMigrationTestTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->executeMigration('d6_user_picture_file');
}
/**
* Tests the Drupal 6 user pictures to Drupal 8 migration.
*/
public function testUserPictures() {
$file_ids = array();
foreach ($this->migration->getIdMap() as $destination_ids) {
$file_ids[] = reset($destination_ids);
}
$files = File::loadMultiple($file_ids);
/** @var \Drupal\file\FileInterface $file */
$file = array_shift($files);
$this->assertIdentical('image-test.jpg', $file->getFilename());
$this->assertIdentical('public://image-test.jpg', $file->getFileUri());
$this->assertIdentical('2', $file->getOwnerId());
$this->assertIdentical('1901', $file->getSize());
$this->assertIdentical('image/jpeg', $file->getMimeType());
$file = array_shift($files);
$this->assertIdentical('image-test.png', $file->getFilename());
$this->assertIdentical('public://image-test.png', $file->getFileUri());
$this->assertIdentical('8', $file->getOwnerId());
$this->assertFalse($files);
}
}

View file

@ -0,0 +1,71 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\user\Entity\User;
/**
* User profile values migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileValuesTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['language'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'language',
'user_profile_field',
'user_profile_field_instance',
'user_profile_entity_display',
'user_profile_entity_form_display',
]);
$this->migrateUsers(FALSE);
$this->executeMigration('d6_profile_values');
}
/**
* Tests Drupal 6 profile values to Drupal 8 migration.
*/
public function testUserProfileValues() {
$user = User::load(2);
$this->assertFalse(is_null($user));
$this->assertIdentical('red', $user->profile_color->value);
$expected = <<<EOT
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nulla sapien, congue nec risus ut, adipiscing aliquet felis. Maecenas quis justo vel nulla varius euismod. Quisque metus metus, cursus sit amet sem non, bibendum vehicula elit. Cras dui nisl, eleifend at iaculis vitae, lacinia ut felis. Nullam aliquam ligula volutpat nulla consectetur accumsan. Maecenas tincidunt molestie diam, a accumsan enim fringilla sit amet. Morbi a tincidunt tellus. Donec imperdiet scelerisque porta. Sed quis sem bibendum eros congue sodales. Vivamus vel fermentum est, at rutrum orci. Nunc consectetur purus ut dolor pulvinar, ut volutpat felis congue. Cras tincidunt odio sed neque sollicitudin, vehicula tempor metus scelerisque.
EOT;
$this->assertIdentical($expected, $user->profile_biography->value);
$this->assertIdentical('1', $user->profile_sell_address->value);
$this->assertIdentical('Back\slash', $user->profile_sold_to->value);
$this->assertIdentical('AC/DC', $user->profile_bands[0]->value);
$this->assertIdentical('Eagles', $user->profile_bands[1]->value);
$this->assertIdentical('Elton John', $user->profile_bands[2]->value);
$this->assertIdentical('Lemonheads', $user->profile_bands[3]->value);
$this->assertIdentical('Rolling Stones', $user->profile_bands[4]->value);
$this->assertIdentical('Queen', $user->profile_bands[5]->value);
$this->assertIdentical('The White Stripes', $user->profile_bands[6]->value);
$this->assertIdentical('1974-06-02', $user->profile_birthdate->value);
$this->assertIdentical('http://example.com/blog', $user->profile_blog->uri);
$this->assertNull($user->profile_blog->title);
$this->assertIdentical([], $user->profile_blog->options);
$this->assertIdentical('http://example.com/blog', $user->profile_blog->uri);
$this->assertNull($user->profile_love_migrations->value);
$user = User::load(8);
$this->assertIdentical('Forward/slash', $user->profile_sold_to->value);
$user = User::load(15);
$this->assertIdentical('Dot.in.the.middle', $user->profile_sold_to->value);
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
/**
* Upgrade user roles to user.role.*.yml.
*
* @group migrate_drupal_6
*/
class MigrateUserRoleTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations(['d6_filter_format', 'd6_user_role']);
}
/**
* Helper function to perform assertions on a user role.
*
* @param string $id
* The role ID.
* @param string[] $permissions
* An array of user permissions.
* @param int $lookupId
* The original numeric ID of the role in the source database.
* @param \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map
* The map table plugin.
*/
protected function assertRole($id, array $permissions, $lookupId, MigrateIdMapInterface $id_map) {
/** @var \Drupal\user\RoleInterface $role */
$role = Role::load($id);
$this->assertInstanceOf(RoleInterface::class, $role);
$this->assertSame($permissions, $role->getPermissions());
$this->assertSame([[$id]], $id_map->lookupDestinationIds(['rid' => $lookupId]));
}
/**
* Helper function to test the migration of the user roles. The user roles
* will be re-imported and the tests here will be repeated.
*
* @param \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map
* The map table plugin.
*/
protected function assertRoles(MigrateIdMapInterface $id_map) {
// The permissions for each role are found in the two tables in the Drupal 6
// source database. One is the permission table and the other is the
// filter_format table.
$permissions = [
// From permission table.
'access content',
'migrate test anonymous permission',
// From filter_format tables.
'use text format filtered_html'
];
$this->assertRole('anonymous', $permissions, 1, $id_map);
$permissions = [
// From permission table.
'access comments',
'access content',
'post comments',
'skip comment approval',
'migrate test authenticated permission',
// From filter_format.
'use text format filtered_html',
];
$this->assertRole('authenticated', $permissions, 2, $id_map);
$permissions = [
// From permission table.
'migrate test role 1 test permission',
// From filter format.
'use text format full_html',
'use text format php_code'
];
$this->assertRole('migrate_test_role_1', $permissions, 3, $id_map);
$permissions = [
// From permission table.
'migrate test role 2 test permission',
'use PHP for settings',
'administer contact forms',
'skip comment approval',
'edit own blog content',
'edit any blog content',
'delete own blog content',
'delete any blog content',
'create forum content',
'delete any forum content',
'delete own forum content',
'edit any forum content',
'edit own forum content',
'administer nodes',
'access content overview',
// From filter format.
'use text format php_code',
];
$this->assertRole('migrate_test_role_2', $permissions, 4, $id_map);
// The only permission for this role is a filter format.
$permissions = ['use text format php_code'];
$this->assertRole('migrate_test_role_3_that_is_longer_than_thirty_two_characters', $permissions, 5, $id_map);
}
/**
* Tests user role migration.
*/
public function testUserRole() {
$id_map = $this->getMigration('d6_user_role')->getIdMap();
$this->assertRoles($id_map);
// Test there are no duplicated roles.
$roles = [
'anonymous1',
'authenticated1',
'administrator1',
'migrate_test_role_11',
'migrate_test_role_21',
'migrate_test_role_3_that_is_longer_than_thirty_two_characters1'
];
$this->assertEmpty(Role::loadMultiple($roles));
// Remove the map row for the migrate_test_role_1 role and rerun the
// migration. This will re-import the migrate_test_role_1 role migration
// again.
$this->sourceDatabase->insert('role')
->fields([
'rid' => 6,
'name' => 'migrate test role 4',
])
->execute();
$this->sourceDatabase->insert('permission')
->fields([
'pid' => 7,
'rid' => 6,
'perm' => 'access content',
'tid' => 0,
])
->execute();
$id_map->delete(['rid' => 3]);
$this->executeMigration('d6_user_role');
// Test there are no duplicated roles.
$roles[] = 'migrate_test_role_41';
$this->assertEmpty(Role::loadMultiple($roles));
// Test that the existing roles have not changed.
$this->assertRoles($id_map);
// Test the migration of the new role, migrate_test_role_4.
$permissions = ['access content'];
$this->assertRole('migrate_test_role_4', $permissions, 6, $id_map);
}
}

View file

@ -0,0 +1,173 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\migrate\MigrateExecutable;
use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
use Drupal\user\Entity\User;
use Drupal\file\Entity\File;
use Drupal\Core\Database\Database;
use Drupal\user\RoleInterface;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Users migration.
*
* @group migrate_drupal_6
*/
class MigrateUserTest extends MigrateDrupal6TestBase {
use FileMigrationTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['language'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->installSchema('file', ['file_usage']);
$this->installEntitySchema('node');
$this->installSchema('user', ['users_data']);
// Make sure uid 1 is created.
user_install();
$file = File::create(array(
'fid' => 2,
'uid' => 2,
'filename' => 'image-test.jpg',
'uri' => "public://image-test.jpg",
'filemime' => 'image/jpeg',
'created' => 1,
'changed' => 1,
'status' => FILE_STATUS_PERMANENT,
));
$file->enforceIsNew();
file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png'));
$file->save();
$file = File::create(array(
'fid' => 8,
'uid' => 8,
'filename' => 'image-test.png',
'uri' => "public://image-test.png",
'filemime' => 'image/png',
'created' => 1,
'changed' => 1,
'status' => FILE_STATUS_PERMANENT,
));
$file->enforceIsNew();
file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-2.jpg'));
$file->save();
$this->executeMigration('language');
$this->migrateUsers();
}
/**
* Tests the Drupal6 user to Drupal 8 migration.
*/
public function testUser() {
$users = Database::getConnection('default', 'migrate')
->select('users', 'u')
->fields('u')
->condition('uid', 0, '>')
->execute()
->fetchAll();
foreach ($users as $source) {
// Get roles directly from the source.
$rids = Database::getConnection('default', 'migrate')
->select('users_roles', 'ur')
->fields('ur', array('rid'))
->condition('ur.uid', $source->uid)
->execute()
->fetchCol();
$roles = array(RoleInterface::AUTHENTICATED_ID);
$id_map = $this->getMigration('d6_user_role')->getIdMap();
foreach ($rids as $rid) {
$role = $id_map->lookupDestinationId(array($rid));
$roles[] = reset($role);
}
/** @var \Drupal\user\UserInterface $user */
$user = User::load($source->uid);
$this->assertSame($source->uid, $user->id());
$this->assertSame($source->name, $user->label());
$this->assertSame($source->mail, $user->getEmail());
$this->assertSame($source->created, $user->getCreatedTime());
$this->assertSame($source->access, $user->getLastAccessedTime());
$this->assertSame($source->login, $user->getLastLoginTime());
$is_blocked = $source->status == 0;
$this->assertSame($is_blocked, $user->isBlocked());
$expected_timezone_name = $source->timezone_name ?: $this->config('system.date')->get('timezone.default');
$this->assertSame($expected_timezone_name, $user->getTimeZone());
$this->assertSame($source->init, $user->getInitialEmail());
$this->assertSame($roles, $user->getRoles());
// Ensure the user's langcode, preferred_langcode and
// preferred_admin_langcode are valid.
// $user->getPreferredLangcode() might fallback to default language if the
// user preferred language is not configured on the site. We just want to
// test if the value was imported correctly.
$language_manager = $this->container->get('language_manager');
$default_langcode = $language_manager->getDefaultLanguage()->getId();
if (empty($source->language)) {
$this->assertSame('en', $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
elseif ($language_manager->getLanguage($source->language) === NULL) {
$this->assertSame($default_langcode, $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
else {
$this->assertSame($source->language, $user->langcode->value);
$this->assertSame($source->language, $user->preferred_langcode->value);
$this->assertSame($source->language, $user->preferred_admin_langcode->value);
}
// We have one empty picture in the data so don't try load that.
if (!empty($source->picture)) {
// Test the user picture.
$file = File::load($user->user_picture->target_id);
$this->assertSame(basename($source->picture), $file->getFilename());
}
else {
// Ensure the user does not have a picture.
$this->assertFalse($user->user_picture->target_id, sprintf('User %s does not have a picture', $user->id()));
}
// Use the API to check if the password has been salted and re-hashed to
// conform to Drupal >= 7 for non-admin users.
if ($user->id() != 1) {
$this->assertTrue(\Drupal::service('password')
->check($source->pass_plain, $user->getPassword()));
}
}
// Rollback the migration and make sure everything is deleted but uid 1.
(new MigrateExecutable($this->migration, $this))->rollback();
$users = Database::getConnection('default', 'migrate')
->select('users', 'u')
->fields('u', ['uid'])
->condition('uid', 0, '>')
->execute()
->fetchCol();
foreach ($users as $uid) {
$account = User::load($uid);
if ($uid == 1) {
$this->assertNotNull($account, 'User 1 was preserved after rollback');
}
else {
$this->assertNull($account);
}
}
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Migrates user flood control configuration.
*
* @group user
*/
class MigrateUserFloodTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['user']);
$this->executeMigration('d7_user_flood');
}
/**
* Tests the migration.
*/
public function testMigration() {
$expected = [
'uid_only' => TRUE,
'ip_limit' => 30,
'ip_window' => 7200,
'user_limit' => 22,
'user_window' => 86400,
'_core' => [
'default_config_hash' => 'UYfMzeP1S8jKm9PSvxf7nQNe8DsNS-3bc2WSNNXBQWs',
],
];
$this->assertIdentical($expected, $this->config('user.flood')->get());
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Migrates user mail configuration.
*
* @group user
*/
class MigrateUserMailTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['user']);
$this->executeMigration('d7_user_mail');
}
/**
* Tests the migration.
*/
public function testMigration() {
$config = $this->config('user.mail');
$this->assertIdentical('Your account is approved!', $config->get('status_activated.subject'));
$this->assertIdentical('Your account was activated, and there was much rejoicing.', $config->get('status_activated.body'));
$this->assertIdentical('Fix your password', $config->get('password_reset.subject'));
$this->assertIdentical("Nope! You're locked out forever.", $config->get('password_reset.body'));
$this->assertIdentical('So long, bub', $config->get('cancel_confirm.subject'));
$this->assertIdentical('The gates of Drupal are closed to you. Now you will work in the salt mines.', $config->get('cancel_confirm.body'));
$this->assertIdentical('Gawd made you an account', $config->get('register_admin_created.subject'));
$this->assertIdentical('...and she could take it away.', $config->get('register_admin_created.body'));
$this->assertIdentical('Welcome!', $config->get('register_no_approval_required.subject'));
$this->assertIdentical('You can now log in if you can figure out how to use Drupal!', $config->get('register_no_approval_required.body'));
$this->assertIdentical('Soon...', $config->get('register_pending_approval.subject'));
$this->assertIdentical('...you will join our Circle. Let the Drupal flow through you.', $config->get('register_pending_approval.body'));
$this->assertIdentical('BEGONE!', $config->get('status_blocked.subject'));
$this->assertIdentical('You no longer please the robot overlords. Go to your room and chill out.', $config->get('status_blocked.body'));
}
}

View file

@ -0,0 +1,105 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Core\Database\Database;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
/**
* Upgrade user roles to user.role.*.yml.
*
* @group user
*/
class MigrateUserRoleTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('d7_user_role');
}
/**
* Asserts aspects of a user role config entity.
*
* @param string $id
* The role ID.
* @param string $label
* The role's expected label.
* @param int|null $original_rid
* The original (integer) ID of the role, to check permissions.
*/
protected function assertEntity($id, $label, $original_rid) {
/** @var \Drupal\user\RoleInterface $entity */
$entity = Role::load($id);
$this->assertTrue($entity instanceof RoleInterface);
$this->assertIdentical($label, $entity->label());
if (isset($original_rid)) {
$permissions = Database::getConnection('default', 'migrate')
->select('role_permission', 'rp')
->fields('rp', ['permission'])
->condition('rid', $original_rid)
->execute()
->fetchCol();
$this->assertIdentical($permissions, $entity->getPermissions());
}
}
/**
* Tests user role migration.
*/
public function testUserRole() {
$this->assertEntity('anonymous', 'anonymous user', 1);
$this->assertEntity('authenticated', 'authenticated user', 2);
$this->assertEntity('administrator', 'administrator', 3);
// Test there are no duplicated roles.
$roles = [
'anonymous1',
'authenticated1',
'administrator1',
];
$this->assertEmpty(Role::loadMultiple($roles));
// Remove the map row for the administrator role and rerun the migration.
// This will re-import the administrator role again.
$id_map = $this->getMigration('d7_user_role')->getIdMap();
$id_map->delete(['rid' => 3]);
$this->sourceDatabase->insert('role')
->fields([
'rid' => 4,
'name' => 'test role',
'weight' => 10,
])
->execute();
$this->sourceDatabase->insert('role_permission')
->fields([
'rid' => 4,
'permission' => 'access content',
'module' => 'node',
])
->execute();
$this->executeMigration('d7_user_role');
// Test there are no duplicated roles.
$roles = [
'anonymous1',
'authenticated1',
'administrator1',
];
$this->assertEmpty(Role::loadMultiple($roles));
// Test that the existing roles have not changed.
$this->assertEntity('administrator', 'administrator', 3);
$this->assertEntity('anonymous', 'anonymous user', 1);
$this->assertEntity('authenticated', 'authenticated user', 2);
// Test the migration of the new role, test role.
$this->assertEntity('test_role', 'test role', 4);
}
}

View file

@ -0,0 +1,239 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\comment\Entity\CommentType;
use Drupal\Core\Database\Database;
use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
use Drupal\user\UserInterface;
/**
* Users migration.
*
* @group user
*/
class MigrateUserTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'comment',
'datetime',
'file',
'image',
'language',
'link',
'node',
'system',
'taxonomy',
'telephone',
'text',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Prepare to migrate user pictures as well.
$this->installEntitySchema('file');
$this->createType('page');
$this->createType('article');
$this->createType('blog');
$this->createType('book');
$this->createType('forum');
$this->createType('test_content_type');
Vocabulary::create(['vid' => 'test_vocabulary'])->save();
$this->executeMigrations([
'language',
'user_picture_field',
'user_picture_field_instance',
'd7_user_role',
'd7_field',
'd7_field_instance',
'd7_user',
]);
}
/**
* Creates a node type with a corresponding comment type.
*
* @param string $id
* The node type ID.
*/
protected function createType($id) {
NodeType::create([
'type' => $id,
'label' => $this->randomString(),
])->save();
CommentType::create([
'id' => 'comment_node_' . $id,
'label' => $this->randomString(),
'target_entity_type_id' => 'node',
])->save();
}
/**
* Asserts various aspects of a user account.
*
* @param string $id
* The user ID.
* @param string $label
* The username.
* @param string $mail
* The user's email address.
* @param string $password
* The password for this user.
* @param int $created
* The user's creation time.
* @param int $access
* The last access time.
* @param int $login
* The last login time.
* @param bool $blocked
* Whether or not the account is blocked.
* @param string $langcode
* The user account's language code.
* @param string $timezone
* The user account's timezone name.
* @param string $init
* The user's initial email address.
* @param string[] $roles
* Role IDs the user account is expected to have.
* @param int $field_integer
* The value of the integer field.
* @param int|false $field_file_target_id
* (optional) The target ID of the file field.
* @param bool $has_picture
* (optional) Whether the user is expected to have a picture attached.
*/
protected function assertEntity($id, $label, $mail, $password, $created, $access, $login, $blocked, $langcode, $timezone, $init, $roles, $field_integer, $field_file_target_id = FALSE, $has_picture = FALSE) {
/** @var \Drupal\user\UserInterface $user */
$user = User::load($id);
$this->assertTrue($user instanceof UserInterface);
$this->assertSame($label, $user->label());
$this->assertSame($mail, $user->getEmail());
$this->assertSame($password, $user->getPassword());
$this->assertSame($created, $user->getCreatedTime());
$this->assertSame($access, $user->getLastAccessedTime());
$this->assertSame($login, $user->getLastLoginTime());
$this->assertNotSame($blocked, $user->isBlocked());
// Ensure the user's langcode, preferred_langcode and
// preferred_admin_langcode are valid.
// $user->getPreferredLangcode() might fallback to default language if the
// user preferred language is not configured on the site. We just want to
// test if the value was imported correctly.
$language_manager = $this->container->get('language_manager');
$default_langcode = $language_manager->getDefaultLanguage()->getId();
if ($langcode == '') {
$this->assertSame('en', $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
elseif ($language_manager->getLanguage($langcode) === NULL) {
$this->assertSame($default_langcode, $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
else {
$this->assertSame($langcode, $user->langcode->value);
$this->assertSame($langcode, $user->preferred_langcode->value);
$this->assertSame($langcode, $user->preferred_admin_langcode->value);
}
$this->assertSame($timezone, $user->getTimeZone());
$this->assertSame($init, $user->getInitialEmail());
$this->assertSame($roles, $user->getRoles());
$this->assertSame($has_picture, !$user->user_picture->isEmpty());
if (!is_null($field_integer)) {
$this->assertTrue($user->hasField('field_integer'));
$this->assertEquals($field_integer[0], $user->field_integer->value);
}
if (!empty($field_file_target_id)) {
$this->assertTrue($user->hasField('field_file'));
$this->assertSame($field_file_target_id, $user->field_file->target_id);
}
}
/**
* Tests the Drupal 7 user to Drupal 8 migration.
*/
public function testUser() {
$users = Database::getConnection('default', 'migrate')
->select('users', 'u')
->fields('u')
->condition('uid', 1, '>')
->execute()
->fetchAll();
foreach ($users as $source) {
$rids = Database::getConnection('default', 'migrate')
->select('users_roles', 'ur')
->fields('ur', array('rid'))
->condition('ur.uid', $source->uid)
->execute()
->fetchCol();
$roles = array(RoleInterface::AUTHENTICATED_ID);
$id_map = $this->getMigration('d7_user_role')->getIdMap();
foreach ($rids as $rid) {
$role = $id_map->lookupDestinationId(array($rid));
$roles[] = reset($role);
}
$field_integer = Database::getConnection('default', 'migrate')
->select('field_data_field_integer', 'fi')
->fields('fi', array('field_integer_value'))
->condition('fi.entity_id', $source->uid)
->execute()
->fetchCol();
$field_integer = !empty($field_integer) ? $field_integer : NULL;
$field_file = Database::getConnection('default', 'migrate')
->select('field_data_field_file', 'ff')
->fields('ff', ['field_file_fid'])
->condition('ff.entity_id', $source->uid)
->execute()
->fetchField();
$this->assertEntity(
$source->uid,
$source->name,
$source->mail,
$source->pass,
$source->created,
$source->access,
$source->login,
$source->status,
$source->language,
$source->timezone,
$source->init,
$roles,
$field_integer,
$field_file
);
// Ensure that the user can authenticate.
$this->assertEquals($source->uid, $this->container->get('user.auth')->authenticate($source->name, 'a password'));
// After authenticating the password will be rehashed because the password
// stretching iteration count has changed from 15 in Drupal 7 to 16 in
// Drupal 8.
$user = User::load($source->uid);
$rehash = $user->getPassword();
$this->assertNotEquals($source->pass, $rehash);
// Authenticate again and there should be no re-hash.
$this->assertEquals($source->uid, $this->container->get('user.auth')->authenticate($source->name, 'a password'));
$user = User::load($source->uid);
$this->assertEquals($rehash, $user->getPassword());
}
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests the user migration plugin class.
*
* @group user
*/
class UserMigrationClassTest extends MigrateDrupal7TestBase {
/**
* Tests d6_profile_values builder.
*
* Ensures profile fields are merged into the d6_profile_values migration's
* process pipeline.
*/
public function testClass() {
$migration = $this->getMigration('d7_user');
/** @var \Drupal\migrate\Plugin\MigrationInterface[] $migrations */
$this->assertIdentical('d7_user', $migration->id());
$process = $migration->getProcess();
$this->assertIdentical('field_file', $process['field_file'][0]['source']);
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the profile_field source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\ProfileField
* @group user
*/
class ProfileFieldTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [
[
'source_data' => [],
'expected_data' => [],
],
];
$profile_fields = [
[
'fid' => 1,
'title' => 'First name',
'name' => 'profile_first_name',
'explanation' => 'First name user',
'category' => 'profile',
'page' => '',
'type' => 'textfield',
'weight' => 0,
'required' => 1,
'register' => 0,
'visibility' => 2,
'autocomplete' => 0,
'options' => '',
],
[
'fid' => 2,
'title' => 'Last name',
'name' => 'profile_last_name',
'explanation' => 'Last name user',
'category' => 'profile',
'page' => '',
'type' => 'textfield',
'weight' => 0,
'required' => 0,
'register' => 0,
'visibility' => 2,
'autocomplete' => 0,
'options' => '',
],
[
'fid' => 3,
'title' => 'Policy',
'name' => 'profile_policy',
'explanation' => 'A checkbox that say if you accept policy of website',
'category' => 'profile',
'page' => '',
'type' => 'checkbox',
'weight' => 0,
'required' => 1,
'register' => 1,
'visibility' => 2,
'autocomplete' => 0,
'options' => '',
],
[
'fid' => 4,
'title' => 'Color',
'name' => 'profile_color',
'explanation' => 'A selection that allows user to select a color',
'category' => 'profile',
'page' => '',
'type' => 'selection',
'weight' => 0,
'required' => 0,
'register' => 0,
'visibility' => 2,
'autocomplete' => 0,
'options' => "red\nblue\ngreen",
],
];
$tests[0]['source_data']['profile_fields'] = $profile_fields;
// Profile values are merged with pre-set options of a "selection" field.
$tests[0]['source_data']['profile_values'] = [
[
'fid' => 4,
'uid' => 1,
'value' => 'yellow',
]
];
// Expected options are:
// for "checkbox" fields - array with NULL options
// for "selection" fields - options in both keys and values
$expected_field_options = [
'',
'',
[NULL, NULL],
[
'red' => 'red',
'blue' => 'blue',
'green' => 'green',
'yellow' => 'yellow',
]
];
$tests[0]['expected_data'] = $profile_fields;
foreach ($tests[0]['expected_data'] as $delta => $row) {
$tests[0]['expected_data'][$delta]['options'] = $expected_field_options[$delta];
}
return $tests;
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the user_picture_instance source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\UserPictureInstance
* @group user
*/
class UserPictureInstanceTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['variable'] = [
[
'name' => 'file_directory',
'value' => serialize(NULL),
],
[
'name' => 'user_picture_file_size',
'value' => serialize(128),
],
[
'name' => 'user_picture_dimensions',
'value' => serialize('128x128'),
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'id' => '',
'file_directory' => 'pictures',
'max_filesize' => '128KB',
'max_resolution' => '128x128',
],
];
return $tests;
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_profile_field_values source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\ProfileFieldValues
* @group user
*/
class ProfileFieldValuesTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['profile_values'] = [
[
'fid' => '8',
'uid' => '2',
'value' => 'red',
],
[
'fid' => '9',
'uid' => '2',
'value' => 'Lorem ipsum dolor sit amet...',
],
];
$tests[0]['source_data']['profile_fields'] = [
[
'fid' => '8',
'title' => 'Favorite color',
'name' => 'profile_color',
'explanation' => 'List your favorite color',
'category' => 'Personal information',
'page' => 'Peole whose favorite color is %value',
'type' => 'textfield',
'weight' => '-10',
'required' => '0',
'register' => '1',
'visibility' => '2',
'autocomplete' => '1',
'options' => '',
],
[
'fid' => '9',
'title' => 'Biography',
'name' => 'profile_biography',
'explanation' => 'Tell people a little bit about yourself',
'category' => 'Personal information',
'page' => '',
'type' => 'textarea',
'weight' => '-8',
'required' => '0',
'register' => '0',
'visibility' => '2',
'autocomplete' => '0',
'options' => '',
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'profile_color' => ['red'],
'profile_biography' => ['Lorem ipsum dolor sit amet...'],
'uid' => '2',
],
];
return $tests;
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user_role source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\Role
* @group user
*/
class RoleTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [
[
'source_data' => [],
'expected_data' => [],
],
];
$roles = [
[
'rid' => 1,
'name' => 'anonymous user',
'permissions' => [
'access content',
],
],
[
'rid' => 2,
'name' => 'authenticated user',
'permissions' => [
'access comments',
'access content',
'post comments',
'post comments without approval',
],
],
[
'rid' => 3,
'name' => 'administrator',
'permissions' => [
'access comments',
'administer comments',
'post comments',
'post comments without approval',
'access content',
'administer content types',
'administer nodes',
],
],
];
// The source data.
foreach ($roles as $role) {
$tests[0]['source_data']['permission'][] = [
'rid' => $role['rid'],
'perm' => implode(', ', $role['permissions']),
];
unset($role['permissions']);
$tests[0]['source_data']['role'][] = $role;
}
$tests[0]['source_data']['filter_formats'] = [
[
'format' => 1,
'roles' => '',
],
];
// The expected results.
$tests[0]['expected_data'] = $roles;
return $tests;
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user_picture_file source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\UserPictureFile
* @group user
*/
class UserPictureFileTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['users'] = [
[
'uid' => '2',
'picture' => 'core/modules/simpletest/files/image-test.jpg',
],
[
'uid' => '15',
'picture' => '',
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'uid' => '2',
'picture' => 'core/modules/simpletest/files/image-test.jpg',
],
];
return $tests;
}
}

View file

@ -0,0 +1,46 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user_picture source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\UserPicture
* @group user
*/
class UserPictureTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['users'] = [
[
'uid' => 1,
'access' => 1382835435,
'picture' => 'sites/default/files/pictures/picture-1.jpg',
],
[
'uid' => 2,
'access' => 1382835436,
'picture' => 'sites/default/files/pictures/picture-2.jpg',
],
];
// User picture data model is identical in source input and output.
$tests[0]['expected_data'] = $tests[0]['source_data']['users'];
return $tests;
}
}

View file

@ -0,0 +1,83 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\User
* @group user
*/
class UserTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['users'] = [
[
'uid' => 2,
'name' => 'admin',
'pass' => '1234',
'mail' => 'admin@example.com',
'theme' => '',
'signature' => '',
'signature_format' => 0,
'created' => 1279402616,
'access' => 1322981278,
'login' => 1322699994,
'status' => 0,
'timezone' => 'America/Lima',
'language' => 'en',
// @todo Add the file when needed.
'picture' => 'sites/default/files/pictures/picture-1.jpg',
'init' => 'admin@example.com',
'data' => NULL,
],
[
'uid' => 4,
'name' => 'alice',
// @todo d6 hash?
'pass' => '1234',
'mail' => 'alice@example.com',
'theme' => '',
'signature' => '',
'signature_format' => 0,
'created' => 1322981368,
'access' => 1322982419,
'login' => 132298140,
'status' => 0,
'timezone' => 'America/Lima',
'language' => 'en',
'picture' => '',
'init' => 'alice@example.com',
'data' => NULL,
],
];
// getDatabase() will not create empty tables, so we need to insert data
// even if it's irrelevant to the test.
$tests[0]['source_data']['users_roles'] = [
[
'uid' => 99,
'rid' => 99,
],
];
// The expected results.
$tests[0]['expected_data'] = $tests[0]['source_data']['users'];
return $tests;
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d7_user_role source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d7\Role
* @group user
*/
class RoleTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['migrate_drupal', 'user'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$expected = [
[
'rid' => 1,
'name' => 'anonymous user',
'permissions' => [
'access content',
],
],
[
'rid' => 2,
'name' => 'authenticated user',
'permissions' => [
'access comments',
'access content',
'post comments',
'post comments without approval',
],
],
[
'rid' => 3,
'name' => 'administrator',
'permissions' => [
'access comments',
'administer comments',
'post comments',
'post comments without approval',
'access content',
'administer content types',
'administer nodes',
],
],
];
$data = [
[[], $expected],
];
foreach ($expected as $row) {
foreach ($row['permissions'] as $permission) {
$data[0][0]['role_permission'][] = [
'permission' => $permission,
'rid' => $row['rid'],
];
}
unset($row['permissions']);
$data[0][0]['role'][] = $row;
}
return $data;
}
}

View file

@ -0,0 +1,120 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d7_user source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d7\User
* @group user
*/
class UserTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['field_config_instance'] = [
[
'id' => '33',
'field_id' => '11',
'field_name' => 'field_file',
'entity_type' => 'user',
'bundle' => 'user',
'data' => 'a:0:{}',
'deleted' => '0',
],
];
$tests[0]['source_data']['field_data_field_file'] = [
[
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => 0,
'entity_id' => 2,
'revision_id' => NULL,
'language' => 'und',
'delta' => 0,
'field_file_fid' => 99,
'field_file_display' => 1,
'field_file_description' => 'None',
],
];
$tests[0]['source_data']['role'] = [
[
'rid' => 2,
'name' => 'authenticated user',
'weight' => 0,
],
];
$tests[0]['source_data']['users'] = [
[
'uid' => '2',
'name' => 'Odo',
'pass' => '$S$DVpvPItXvnsmF3giVEe7Jy2lG.SCoEs8uKwpHsyPvdeNAaNZYxZ8',
'mail' => 'odo@local.host',
'theme' => '',
'signature' => '',
'signature_format' => 'filtered_html',
'created' => '1432750741',
'access' => '0',
'login' => '0',
'status' => '1',
'timezone' => 'America/Chicago',
'language' => '',
'picture' => '0',
'init' => 'odo@local.host',
'data' => 'a:1:{s:7:"contact";i:1;}',
],
];
$tests[0]['source_data']['users_roles'] = [
[
'uid' => 2,
'rid' => 2,
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'uid' => '2',
'name' => 'Odo',
'pass' => '$S$DVpvPItXvnsmF3giVEe7Jy2lG.SCoEs8uKwpHsyPvdeNAaNZYxZ8',
'mail' => 'odo@local.host',
'signature' => '',
'signature_format' => 'filtered_html',
'created' => '1432750741',
'access' => '0',
'login' => '0',
'status' => '1',
'timezone' => 'America/Chicago',
'language' => '',
'picture' => '0',
'init' => 'odo@local.host',
'roles' => [2],
'data' => [
'contact' => 1,
],
'field_file' => [
[
'fid' => 99,
'display' => 1,
'description' => 'None',
],
],
],
];
return $tests;
}
}

View file

@ -0,0 +1,146 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\Lock\DatabaseLockBackend;
use Drupal\Core\Database\Database;
/**
* Tests the temporary object storage system.
*
* @group user
* @see \Drupal\Core\TempStore\TempStore.
*/
class TempStoreDatabaseTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user');
/**
* A key/value store factory.
*
* @var \Drupal\user\SharedTempStoreFactory
*/
protected $storeFactory;
/**
* The name of the key/value collection to set and retrieve.
*
* @var string
*/
protected $collection;
/**
* An array of (fake) user IDs.
*
* @var array
*/
protected $users = array();
/**
* An array of random stdClass objects.
*
* @var array
*/
protected $objects = array();
protected function setUp() {
parent::setUp();
// Install system tables to test the key/value storage without installing a
// full Drupal environment.
$this->installSchema('system', array('key_value_expire'));
// Create several objects for testing.
for ($i = 0; $i <= 3; $i++) {
$this->objects[$i] = $this->randomObject();
}
}
/**
* Tests the UserTempStore API.
*/
public function testUserTempStore() {
// Create a key/value collection.
$factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend(Database::getConnection()), $this->container->get('request_stack'));
$collection = $this->randomMachineName();
// Create two mock users.
for ($i = 0; $i <= 1; $i++) {
$users[$i] = mt_rand(500, 5000000);
// Storing the SharedTempStore objects in a class member variable causes a
// fatal exception, because in that situation garbage collection is not
// triggered until the test class itself is destructed, after tearDown()
// has deleted the database tables. Store the objects locally instead.
$stores[$i] = $factory->get($collection, $users[$i]);
}
$key = $this->randomMachineName();
// Test that setIfNotExists() succeeds only the first time.
for ($i = 0; $i <= 1; $i++) {
// setIfNotExists() should be TRUE the first time (when $i is 0) and
// FALSE the second time (when $i is 1).
$this->assertEqual(!$i, $stores[0]->setIfNotExists($key, $this->objects[$i]));
$metadata = $stores[0]->getMetadata($key);
$this->assertEqual($users[0], $metadata->owner);
$this->assertIdenticalObject($this->objects[0], $stores[0]->get($key));
// Another user should get the same result.
$metadata = $stores[1]->getMetadata($key);
$this->assertEqual($users[0], $metadata->owner);
$this->assertIdenticalObject($this->objects[0], $stores[1]->get($key));
}
// Remove the item and try to set it again.
$stores[0]->delete($key);
$stores[0]->setIfNotExists($key, $this->objects[1]);
// This time it should succeed.
$this->assertIdenticalObject($this->objects[1], $stores[0]->get($key));
// This user can update the object.
$stores[0]->set($key, $this->objects[2]);
$this->assertIdenticalObject($this->objects[2], $stores[0]->get($key));
// The object is the same when another user loads it.
$this->assertIdenticalObject($this->objects[2], $stores[1]->get($key));
// This user should be allowed to get, update, delete.
$this->assertTrue($stores[0]->getIfOwner($key) instanceof \stdClass);
$this->assertTrue($stores[0]->setIfOwner($key, $this->objects[1]));
$this->assertTrue($stores[0]->deleteIfOwner($key));
// Another user can update the object and become the owner.
$stores[1]->set($key, $this->objects[3]);
$this->assertIdenticalObject($this->objects[3], $stores[0]->get($key));
$this->assertIdenticalObject($this->objects[3], $stores[1]->get($key));
$metadata = $stores[1]->getMetadata($key);
$this->assertEqual($users[1], $metadata->owner);
// The first user should be informed that the second now owns the data.
$metadata = $stores[0]->getMetadata($key);
$this->assertEqual($users[1], $metadata->owner);
// The first user should no longer be allowed to get, update, delete.
$this->assertNull($stores[0]->getIfOwner($key));
$this->assertFalse($stores[0]->setIfOwner($key, $this->objects[1]));
$this->assertFalse($stores[0]->deleteIfOwner($key));
// Now manually expire the item (this is not exposed by the API) and then
// assert it is no longer accessible.
db_update('key_value_expire')
->fields(array('expire' => REQUEST_TIME - 1))
->condition('collection', "user.shared_tempstore.$collection")
->condition('name', $key)
->execute();
$this->assertFalse($stores[0]->get($key));
$this->assertFalse($stores[1]->get($key));
}
}

View file

@ -0,0 +1,146 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Core\Form\FormState;
use Drupal\KernelTests\KernelTestBase;
/**
* Verifies that the field order in user account forms is compatible with
* password managers of web browsers.
*
* @group user
*/
class UserAccountFormFieldsTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user', 'field');
/**
* Tests the root user account form section in the "Configure site" form.
*/
function testInstallConfigureForm() {
require_once \Drupal::root() . '/core/includes/install.core.inc';
require_once \Drupal::root() . '/core/includes/install.inc';
$install_state = install_state_defaults();
$form_state = new FormState();
$form_state->addBuildInfo('args', [&$install_state]);
$form = $this->container->get('form_builder')
->buildForm('Drupal\Core\Installer\Form\SiteConfigureForm', $form_state);
// Verify name and pass field order.
$this->assertFieldOrder($form['admin_account']['account']);
// Verify that web browsers may autocomplete the email value and
// autofill/prefill the name and pass values.
foreach (array('mail', 'name', 'pass') as $key) {
$this->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'$key' field: 'autocomplete' attribute not found.");
}
}
/**
* Tests the user registration form.
*/
function testUserRegistrationForm() {
// Install default configuration; required for AccountFormController.
$this->installConfig(array('user'));
// Disable email confirmation to unlock the password field.
$this->config('user.settings')
->set('verify_mail', FALSE)
->save();
$form = $this->buildAccountForm('register');
// Verify name and pass field order.
$this->assertFieldOrder($form['account']);
// Verify that web browsers may autocomplete the email value and
// autofill/prefill the name and pass values.
foreach (array('mail', 'name', 'pass') as $key) {
$this->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'$key' field: 'autocomplete' attribute not found.");
}
}
/**
* Tests the user edit form.
*/
function testUserEditForm() {
// Install default configuration; required for AccountFormController.
$this->installConfig(array('user'));
// Install the router table and then rebuild.
\Drupal::service('router.builder')->rebuild();
$form = $this->buildAccountForm('default');
// Verify name and pass field order.
$this->assertFieldOrder($form['account']);
// Verify that autocomplete is off on all account fields.
foreach (array('mail', 'name', 'pass') as $key) {
$this->assertIdentical($form['account'][$key]['#attributes']['autocomplete'], 'off', "'$key' field: 'autocomplete' attribute is 'off'.");
}
}
/**
* Asserts that the 'name' form element is directly before the 'pass' element.
*
* @param array $elements
* A form array section that contains the user account form elements.
*/
protected function assertFieldOrder(array $elements) {
$name_index = 0;
$name_weight = 0;
$pass_index = 0;
$pass_weight = 0;
$index = 0;
foreach ($elements as $key => $element) {
if ($key === 'name') {
$name_index = $index;
$name_weight = $element['#weight'];
$this->assertTrue($element['#sorted'], "'name' field is #sorted.");
}
elseif ($key === 'pass') {
$pass_index = $index;
$pass_weight = $element['#weight'];
$this->assertTrue($element['#sorted'], "'pass' field is #sorted.");
}
$index++;
}
$this->assertEqual($name_index, $pass_index - 1, "'name' field ($name_index) appears before 'pass' field ($pass_index).");
$this->assertTrue($name_weight < $pass_weight, "'name' field weight ($name_weight) is smaller than 'pass' field weight ($pass_weight).");
}
/**
* Builds the user account form for a given operation.
*
* @param string $operation
* The entity operation; one of 'register' or 'default'.
*
* @return array
* The form array.
*/
protected function buildAccountForm($operation) {
// @see HtmlEntityFormController::getFormObject()
$entity_type = 'user';
$fields = array();
if ($operation != 'register') {
$fields['uid'] = 2;
}
$entity = $this->container->get('entity.manager')
->getStorage($entity_type)
->create($fields);
$this->container->get('entity.manager')
->getFormObject($entity_type, $operation)
->setEntity($entity);
// @see EntityFormBuilder::getForm()
return $this->container->get('entity.form_builder')->getForm($entity, $operation);
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
/**
* Ensures the user action for adding and removing roles have valid config
* schema.
*
* @group user
*/
class UserActionConfigSchemaTest extends KernelTestBase {
use SchemaCheckTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user');
/**
* Tests whether the user action config schema are valid.
*/
function testValidUserActionConfigSchema() {
$rid = strtolower($this->randomMachineName(8));
Role::create(array('id' => $rid))->save();
// Test user_add_role_action configuration.
$config = $this->config('system.action.user_add_role_action.' . $rid);
$this->assertEqual($config->get('id'), 'user_add_role_action.' . $rid);
$this->assertConfigSchema(\Drupal::service('config.typed'), $config->getName(), $config->get());
// Test user_remove_role_action configuration.
$config = $this->config('system.action.user_remove_role_action.' . $rid);
$this->assertEqual($config->get('id'), 'user_remove_role_action.' . $rid);
$this->assertConfigSchema(\Drupal::service('config.typed'), $config->getName(), $config->get());
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\user\Entity\Role;
/**
* Tests the user reference field functionality.
*
* @group user
*/
class UserEntityReferenceTest extends EntityKernelTestBase {
use EntityReferenceTestTrait;
/**
* A randomly-generated role for testing purposes.
*
* @var \Drupal\user\RoleInterface
*/
protected $role1;
/**
* A randomly-generated role for testing purposes.
*
* @var \Drupal\user\RoleInterface
*/
protected $role2;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->role1 = Role::create(array(
'id' => strtolower($this->randomMachineName(8)),
'label' => $this->randomMachineName(8),
));
$this->role1->save();
$this->role2 = Role::create(array(
'id' => strtolower($this->randomMachineName(8)),
'label' => $this->randomMachineName(8),
));
$this->role2->save();
$this->createEntityReferenceField('user', 'user', 'user_reference', 'User reference', 'user');
}
/**
* Tests user selection by roles.
*/
function testUserSelectionByRole() {
$field_definition = FieldConfig::loadByName('user', 'user', 'user_reference');
$handler_settings = $field_definition->getSetting('handler_settings');
$handler_settings['filter']['role'] = array(
$this->role1->id() => $this->role1->id(),
$this->role2->id() => 0,
);
$handler_settings['filter']['type'] = 'role';
$field_definition->setSetting('handler_settings', $handler_settings);
$field_definition->save();
$user1 = $this->createUser(array('name' => 'aabb'));
$user1->addRole($this->role1->id());
$user1->save();
$user2 = $this->createUser(array('name' => 'aabbb'));
$user2->addRole($this->role1->id());
$user2->save();
$user3 = $this->createUser(array('name' => 'aabbbb'));
$user3->addRole($this->role2->id());
$user3->save();
/** @var \Drupal\Core\Entity\EntityAutocompleteMatcher $autocomplete */
$autocomplete = \Drupal::service('entity.autocomplete_matcher');
$matches = $autocomplete->getMatches('user', 'default', $field_definition->getSetting('handler_settings'), 'aabb');
$this->assertEqual(count($matches), 2);
$users = array();
foreach ($matches as $match) {
$users[] = $match['label'];
}
$this->assertTrue(in_array($user1->label(), $users));
$this->assertTrue(in_array($user2->label(), $users));
$this->assertFalse(in_array($user3->label(), $users));
$matches = $autocomplete->getMatches('user', 'default', $field_definition->getSetting('handler_settings'), 'aabbbb');
$this->assertEqual(count($matches), 0, '');
}
}

View file

@ -0,0 +1,68 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
/**
* Tests the user entity class.
*
* @group user
* @see \Drupal\user\Entity\User
*/
class UserEntityTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user', 'field');
/**
* Tests some of the methods.
*
* @see \Drupal\user\Entity\User::getRoles()
* @see \Drupal\user\Entity\User::addRole()
* @see \Drupal\user\Entity\User::removeRole()
*/
public function testUserMethods() {
$role_storage = $this->container->get('entity.manager')->getStorage('user_role');
$role_storage->create(array('id' => 'test_role_one'))->save();
$role_storage->create(array('id' => 'test_role_two'))->save();
$role_storage->create(array('id' => 'test_role_three'))->save();
$values = array(
'uid' => 1,
'roles' => array('test_role_one'),
);
$user = User::create($values);
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertFalse($user->hasRole('test_role_two'));
$this->assertEqual(array(RoleInterface::AUTHENTICATED_ID, 'test_role_one'), $user->getRoles());
$user->addRole('test_role_one');
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertFalse($user->hasRole('test_role_two'));
$this->assertEqual(array(RoleInterface::AUTHENTICATED_ID, 'test_role_one'), $user->getRoles());
$user->addRole('test_role_two');
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
$this->assertEqual(array(RoleInterface::AUTHENTICATED_ID, 'test_role_one', 'test_role_two'), $user->getRoles());
$user->removeRole('test_role_three');
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
$this->assertEqual(array(RoleInterface::AUTHENTICATED_ID, 'test_role_one', 'test_role_two'), $user->getRoles());
$user->removeRole('test_role_one');
$this->assertFalse($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
$this->assertEqual(array(RoleInterface::AUTHENTICATED_ID, 'test_role_two'), $user->getRoles());
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\user\Entity\User;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests available user fields in twig.
*
* @group user
*/
class UserFieldsTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user', 'system'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
// Set up a test theme that prints the user's mail field.
\Drupal::service('theme_handler')->install(array('user_test_theme'));
\Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('user_test_theme'));
// Clear the theme registry.
$this->container->set('theme.registry', NULL);
}
/**
* Tests account's available fields.
*/
function testUserFields() {
// Create the user to test the user fields.
$user = User::create([
'name' => 'foobar',
'mail' => 'foobar@example.com',
]);
$build = user_view($user);
$output = \Drupal::service('renderer')->renderRoot($build);
$this->setRawContent($output);
$userEmail = $user->getEmail();
$this->assertText($userEmail, "User's mail field is found in the twig template");
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests user_install().
*
* @group user
*/
class UserInstallTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('user');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container->get('module_handler')->loadInclude('user', 'install');
$this->installEntitySchema('user');
user_install();
}
/**
* Test that the initial users have correct values.
*/
public function testUserInstall() {
$result = db_query('SELECT u.uid, u.uuid, u.langcode, uf.status FROM {users} u INNER JOIN {users_field_data} uf ON u.uid=uf.uid ORDER BY u.uid')
->fetchAllAssoc('uid');
$anon = $result[0];
$admin = $result[1];
$this->assertFalse(empty($anon->uuid), 'Anon user has a UUID');
$this->assertFalse(empty($admin->uuid), 'Admin user has a UUID');
// Test that the anonymous and administrators languages are equal to the
// site's default language.
$this->assertEqual($anon->langcode, \Drupal::languageManager()->getDefaultLanguage()->getId());
$this->assertEqual($admin->langcode, \Drupal::languageManager()->getDefaultLanguage()->getId());
// Test that the administrator is active.
$this->assertEqual($admin->status, 1);
// Test that the anonymous user is blocked.
$this->assertEqual($anon->status, 0);
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
/**
* Tests the handling of user_role entity from the user module
*
* @group user
*/
class UserRoleDeleteTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user', 'field');
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
}
/**
* Tests removal of role references on role entity delete.
*
* @see user_user_role_delete()
*/
public function testRoleDeleteUserRoleReferenceDelete() {
// Create two test roles.
$role_storage = $this->container->get('entity.manager')->getStorage('user_role');
$role_storage->create(array('id' => 'test_role_one'))->save();
$role_storage->create(array('id' => 'test_role_two'))->save();
// Create user and assign both test roles.
$values = array(
'uid' => 1,
'name' => $this->randomString(),
'roles' => array('test_role_one', 'test_role_two'),
);
$user = User::create($values);
$user->save();
// Check that user has both roles.
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
// Delete test role one.
$test_role_one = $role_storage->load('test_role_one');
$test_role_one->delete();
// Load user again from the database.
$user = User::load($user->id());
// Check that user does not have role one anymore, still has role two.
$this->assertFalse($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
// Create new role with same name.
$role_storage->create(array('id' => 'test_role_one'))->save();
// Load user again from the database.
$user = User::load($user->id());
// Check that user does not have role one.
$this->assertFalse($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
/**
* Tests user saving status.
*
* @group user
*/
class UserSaveStatusTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('system', 'user', 'field');
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
}
/**
* Test SAVED_NEW and SAVED_UPDATED statuses for user entity type.
*/
function testUserSaveStatus() {
// Create a new user.
$values = array(
'uid' => 1,
'name' => $this->randomMachineName(),
);
$user = User::create($values);
// Test SAVED_NEW.
$return = $user->save();
$this->assertEqual($return, SAVED_NEW, "User was saved with SAVED_NEW status.");
// Test SAVED_UPDATED.
$user->name = $this->randomMachineName();
$return = $user->save();
$this->assertEqual($return, SAVED_UPDATED, "User was saved with SAVED_UPDATED status.");
}
}

View file

@ -0,0 +1,216 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Render\Element\Email;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
/**
* Verify that user validity checks behave as designed.
*
* @group user
*/
class UserValidationTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('field', 'user', 'system');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installSchema('system', array('sequences'));
// Make sure that the default roles exist.
$this->installConfig(array('user'));
}
/**
* Tests user name validation.
*/
function testUsernames() {
$test_cases = array( // '<username>' => array('<description>', 'assert<testName>'),
'foo' => array('Valid username', 'assertNull'),
'FOO' => array('Valid username', 'assertNull'),
'Foo O\'Bar' => array('Valid username', 'assertNull'),
'foo@bar' => array('Valid username', 'assertNull'),
'foo@example.com' => array('Valid username', 'assertNull'),
'foo@-example.com' => array('Valid username', 'assertNull'), // invalid domains are allowed in usernames
'þòøÇߪř€' => array('Valid username', 'assertNull'),
'foo+bar' => array('Valid username', 'assertNull'), // '+' symbol is allowed
'ᚠᛇᚻ᛫ᛒᛦᚦ' => array('Valid UTF8 username', 'assertNull'), // runes
' foo' => array('Invalid username that starts with a space', 'assertNotNull'),
'foo ' => array('Invalid username that ends with a space', 'assertNotNull'),
'foo bar' => array('Invalid username that contains 2 spaces \'&nbsp;&nbsp;\'', 'assertNotNull'),
'' => array('Invalid empty username', 'assertNotNull'),
'foo/' => array('Invalid username containing invalid chars', 'assertNotNull'),
'foo' . chr(0) . 'bar' => array('Invalid username containing chr(0)', 'assertNotNull'), // NULL
'foo' . chr(13) . 'bar' => array('Invalid username containing chr(13)', 'assertNotNull'), // CR
str_repeat('x', USERNAME_MAX_LENGTH + 1) => array('Invalid excessively long username', 'assertNotNull'),
);
foreach ($test_cases as $name => $test_case) {
list($description, $test) = $test_case;
$result = user_validate_name($name);
$this->$test($result, $description . ' (' . $name . ')');
}
}
/**
* Runs entity validation checks.
*/
function testValidation() {
$user = User::create(array(
'name' => 'test',
'mail' => 'test@example.com',
));
$violations = $user->validate();
$this->assertEqual(count($violations), 0, 'No violations when validating a default user.');
// Only test one example invalid name here, the rest is already covered in
// the testUsernames() method in this class.
$name = $this->randomMachineName(61);
$user->set('name', $name);
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when name is too long.');
$this->assertEqual($violations[0]->getPropertyPath(), 'name');
$this->assertEqual($violations[0]->getMessage(), t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => 60)));
// Create a second test user to provoke a name collision.
$user2 = User::create([
'name' => 'existing',
'mail' => 'existing@example.com',
]);
$user2->save();
$user->set('name', 'existing');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found on name collision.');
$this->assertEqual($violations[0]->getPropertyPath(), 'name');
$this->assertEqual($violations[0]->getMessage(), t('The username %name is already taken.', array('%name' => 'existing')));
// Make the name valid.
$user->set('name', $this->randomMachineName());
$user->set('mail', 'invalid');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when email is invalid');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
$this->assertEqual($violations[0]->getMessage(), t('This value is not a valid email address.'));
$mail = $this->randomMachineName(Email::EMAIL_MAX_LENGTH - 11) . '@example.com';
$user->set('mail', $mail);
$violations = $user->validate();
// @todo There are two violations because EmailItem::getConstraints()
// overlaps with the implicit constraint of the 'email' property type used
// in EmailItem::propertyDefinitions(). Resolve this in
// https://www.drupal.org/node/2023465.
$this->assertEqual(count($violations), 2, 'Violations found when email is too long');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
$this->assertEqual($violations[0]->getMessage(), t('%name: the email address can not be longer than @max characters.', array('%name' => $user->get('mail')->getFieldDefinition()->getLabel(), '@max' => Email::EMAIL_MAX_LENGTH)));
$this->assertEqual($violations[1]->getPropertyPath(), 'mail.0.value');
$this->assertEqual($violations[1]->getMessage(), t('This value is not a valid email address.'));
// Provoke an email collision with an existing user.
$user->set('mail', 'existing@example.com');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when email already exists.');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail');
$this->assertEqual($violations[0]->getMessage(), t('The email address %mail is already taken.', array('%mail' => 'existing@example.com')));
$user->set('mail', NULL);
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Email addresses may not be removed');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail');
$this->assertEqual($violations[0]->getMessage(), t('@name field is required.', array('@name' => $user->getFieldDefinition('mail')->getLabel())));
$user->set('mail', 'someone@example.com');
$user->set('timezone', $this->randomString(33));
$this->assertLengthViolation($user, 'timezone', 32, 2, 1);
$user->set('timezone', 'invalid zone');
$this->assertAllowedValuesViolation($user, 'timezone');
$user->set('timezone', NULL);
$user->set('init', 'invalid');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when init email is invalid');
$user->set('init', NULL);
$user->set('langcode', 'invalid');
$this->assertAllowedValuesViolation($user, 'langcode');
$user->set('langcode', NULL);
// Only configurable langcodes are allowed for preferred languages.
$user->set('preferred_langcode', Language::LANGCODE_NOT_SPECIFIED);
$this->assertAllowedValuesViolation($user, 'preferred_langcode');
$user->set('preferred_langcode', NULL);
$user->set('preferred_admin_langcode', Language::LANGCODE_NOT_SPECIFIED);
$this->assertAllowedValuesViolation($user, 'preferred_admin_langcode');
$user->set('preferred_admin_langcode', NULL);
Role::create(array('id' => 'role1'))->save();
Role::create(array('id' => 'role2'))->save();
// Test cardinality of user roles.
$user = User::create([
'name' => 'role_test',
'mail' => 'test@example.com',
'roles' => array('role1', 'role2'),
]);
$violations = $user->validate();
$this->assertEqual(count($violations), 0);
$user->roles[1]->target_id = 'unknown_role';
$violations = $user->validate();
$this->assertEqual(count($violations), 1);
$this->assertEqual($violations[0]->getPropertyPath(), 'roles.1.target_id');
$this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%entity_type: %name) does not exist.', array('%entity_type' => 'user_role', '%name' => 'unknown_role')));
}
/**
* Verifies that a length violation exists for the given field.
*
* @param \Drupal\core\Entity\EntityInterface $entity
* The entity object to validate.
* @param string $field_name
* The field that violates the maximum length.
* @param int $length
* Number of characters that was exceeded.
* @param int $count
* (optional) The number of expected violations. Defaults to 1.
* @param int $expected_index
* (optional) The index at which to expect the violation. Defaults to 0.
*/
protected function assertLengthViolation(EntityInterface $entity, $field_name, $length, $count = 1, $expected_index = 0) {
$violations = $entity->validate();
$this->assertEqual(count($violations), $count, "Violation found when $field_name is too long.");
$this->assertEqual($violations[$expected_index]->getPropertyPath(), "$field_name.0.value");
$field_label = $entity->get($field_name)->getFieldDefinition()->getLabel();
$this->assertEqual($violations[$expected_index]->getMessage(), t('%name: may not be longer than @max characters.', array('%name' => $field_label, '@max' => $length)));
}
/**
* Verifies that a AllowedValues violation exists for the given field.
*
* @param \Drupal\core\Entity\EntityInterface $entity
* The entity object to validate.
* @param string $field_name
* The name of the field to verify.
*/
protected function assertAllowedValuesViolation(EntityInterface $entity, $field_name) {
$violations = $entity->validate();
$this->assertEqual(count($violations), 1, "Allowed values violation for $field_name found.");
$this->assertEqual($violations[0]->getPropertyPath(), "$field_name.0.value");
$this->assertEqual($violations[0]->getMessage(), t('The value you selected is not a valid choice.'));
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\views\Views;
/**
* Tests the permission field handler.
*
* @group user
* @see \Drupal\user\Plugin\views\field\Permissions
*/
class HandlerFieldPermissionTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_field_permission');
/**
* Tests the permission field handler output.
*/
public function testFieldPermission() {
$this->setupPermissionTestData();
$view = Views::getView('test_field_permission');
$this->executeView($view);
$view->initStyle();
$view->render();
$style_plugin = $view->style_plugin;
$expected_permissions = array();
$expected_permissions[$this->users[0]->id()] = array();
$expected_permissions[$this->users[1]->id()] = array();
$expected_permissions[$this->users[2]->id()][] = t('Administer permissions');
// View user profiles comes first, because we sort by the permission
// machine name.
$expected_permissions[$this->users[3]->id()][] = t('Administer permissions');
$expected_permissions[$this->users[3]->id()][] = t('Administer users');
$expected_permissions[$this->users[3]->id()][] = t('View user information');
foreach ($view->result as $index => $row) {
$uid = $view->field['uid']->getValue($row);
$rendered_permission = $style_plugin->getField($index, 'permission');
$expected_output = implode(', ', $expected_permissions[$uid]);
$this->assertEqual($rendered_permission, $expected_output, 'The right permissions are rendered.');
}
}
}

View file

@ -0,0 +1,95 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\views\Views;
use Drupal\Core\Session\AnonymousUserSession;
/**
* Tests the current user filter handler.
*
* @group user
* @see \Drupal\user\Plugin\views\filter\Current
*/
class HandlerFilterCurrentUserTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_filter_current_user'];
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxy
*/
protected $currentUser;
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp();
$this->currentUser = $this->container->get('current_user');
$this->setupPermissionTestData();
}
/**
* Tests the current user filter handler with anonymous user.
*/
public function testFilterCurrentUserAsAnonymous() {
$column_map = ['uid' => 'uid'];
$this->currentUser->setAccount(new AnonymousUserSession());
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 0;
$this->executeView($view);
$expected[] = ['uid' => 1];
$expected[] = ['uid' => 2];
$expected[] = ['uid' => 3];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map, 'Anonymous account can view all accounts when current filter is FALSE.');
$view->destroy();
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 1;
$this->executeView($view);
$expected = [];
$this->assertIdenticalResultset($view, $expected, $column_map, 'Anonymous account can view zero accounts when current filter is TRUE.');
$view->destroy();
}
/**
* Tests the current user filter handler with logged-in user.
*/
public function testFilterCurrentUserAsUser() {
$column_map = ['uid' => 'uid'];
$user = reset($this->users);
$this->currentUser->setAccount($user);
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 0;
$this->executeView($view);
$expected = [];
$expected[] = ['uid' => 2];
$expected[] = ['uid' => 3];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map, 'User can view all users except itself when current filter is FALSE.');
$view->destroy();
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 1;
$this->executeView($view);
$expected = [];
$expected[] = ['uid' => 1];
$this->assertIdenticalResultset($view, $expected, $column_map, 'User can only view itself when current filter is TRUE.');
$view->destroy();
}
}

View file

@ -0,0 +1,115 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\Component\Utility\Html;
use Drupal\views\Views;
/**
* Tests the permissions filter handler.
*
* @group user
* @see \Drupal\user\Plugin\views\filter\Permissions
*/
class HandlerFilterPermissionTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_filter_permission');
protected $columnMap;
/**
* Tests the permission filter handler.
*
* @todo Fix the different commented out tests by fixing the many to one
* handler handling with the NOT operator.
*/
public function testFilterPermission() {
$this->setupPermissionTestData();
$column_map = array('uid' => 'uid');
$view = Views::getView('test_filter_permission');
// Filter by a non existing permission.
$view->initHandlers();
$view->filter['permission']->value = array('non_existent_permission');
$this->executeView($view);
$this->assertEqual(count($view->result), 4, 'A non existent permission is not filtered so everything is the result.');
$expected[] = array('uid' => 1);
$expected[] = array('uid' => 2);
$expected[] = array('uid' => 3);
$expected[] = array('uid' => 4);
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by a permission.
$view->initHandlers();
$view->filter['permission']->value = array('administer permissions');
$this->executeView($view);
$this->assertEqual(count($view->result), 2);
$expected = array();
$expected[] = array('uid' => 3);
$expected[] = array('uid' => 4);
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by not a permission.
$view->initHandlers();
$view->filter['permission']->operator = 'not';
$view->filter['permission']->value = array('administer users');
$this->executeView($view);
$this->assertEqual(count($view->result), 3);
$expected = array();
$expected[] = array('uid' => 1);
$expected[] = array('uid' => 2);
$expected[] = array('uid' => 3);
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by not multiple permissions, that are present in multiple roles.
$view->initHandlers();
$view->filter['permission']->operator = 'not';
$view->filter['permission']->value = array('administer users', 'administer permissions');
$this->executeView($view);
$this->assertEqual(count($view->result), 2);
$expected = array();
$expected[] = array('uid' => 1);
$expected[] = array('uid' => 2);
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by another permission of a role with multiple permissions.
$view->initHandlers();
$view->filter['permission']->value = array('administer users');
$this->executeView($view);
$this->assertEqual(count($view->result), 1);
$expected = array();
$expected[] = array('uid' => 4);
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
$view->initDisplay();
$view->initHandlers();
// Test the value options.
$value_options = $view->filter['permission']->getValueOptions();
$permission_by_module = [];
$permissions = \Drupal::service('user.permissions')->getPermissions();
foreach ($permissions as $name => $permission) {
$permission_by_module[$permission['provider']][$name] = $permission;
}
foreach (array('system' => 'System', 'user' => 'User') as $module => $title) {
$expected = array_map(function ($permission) {
return Html::escape(strip_tags($permission['title']));
}, $permission_by_module[$module]);
$this->assertEqual($expected, $value_options[$title], 'Ensure the all permissions are available');
}
}
}

View file

@ -0,0 +1,70 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\user\Entity\Role;
use Drupal\views\Entity\View;
use Drupal\views\Views;
/**
* Tests the roles filter handler.
*
* @group user
*
* @see \Drupal\user\Plugin\views\filter\Roles
*/
class HandlerFilterRolesTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_user_name');
/**
* Tests that role filter dependencies are calculated correctly.
*/
public function testDependencies() {
$role = Role::create(['id' => 'test_user_role']);
$role->save();
$view = View::load('test_user_name');
$expected = [
'module' => ['user'],
];
$this->assertEqual($expected, $view->getDependencies());
$display = &$view->getDisplay('default');
$display['display_options']['filters']['roles_target_id'] = [
'id' => 'roles_target_id',
'table' => 'user__roles',
'field' => 'roles_target_id',
'value' => [
'test_user_role' => 'test_user_role',
],
'plugin_id' => 'user_roles',
];
$view->save();
$expected['config'][] = 'user.role.test_user_role';
$this->assertEqual($expected, $view->getDependencies());
$view = Views::getView('test_user_name');
$view->initDisplay();
$view->initHandlers();
$this->assertEqual(array_keys($view->filter['roles_target_id']->getValueOptions()), ['test_user_role']);
$view = View::load('test_user_name');
$display = &$view->getDisplay('default');
$display['display_options']['filters']['roles_target_id'] = [
'id' => 'roles_target_id',
'table' => 'user__roles',
'field' => 'roles_target_id',
'value' => [],
'plugin_id' => 'user_roles',
];
$view->save();
unset($expected['config']);
$this->assertEqual($expected, $view->getDependencies());
}
}

View file

@ -0,0 +1,90 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Tests\ViewTestData;
/**
* Provides a common test base for user views tests.
*/
abstract class UserKernelTestBase extends ViewsKernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('user_test_views', 'user', 'system', 'field');
/**
* Users to use during this test.
*
* @var array
*/
protected $users = array();
/**
* The entity storage for roles.
*
* @var \Drupal\user\RoleStorage
*/
protected $roleStorage;
/**
* The entity storage for users.
*
* @var \Drupal\user\UserStorage
*/
protected $userStorage;
protected function setUp($import_test_views = TRUE) {
parent::setUp();
ViewTestData::createTestViews(get_class($this), array('user_test_views'));
$this->installEntitySchema('user');
$entity_manager = $this->container->get('entity.manager');
$this->roleStorage = $entity_manager->getStorage('user_role');
$this->userStorage = $entity_manager->getStorage('user');
}
/**
* Set some test data for permission related tests.
*/
protected function setupPermissionTestData() {
// Setup a role without any permission.
$this->roleStorage->create(array('id' => 'authenticated'))
->save();
$this->roleStorage->create(array('id' => 'no_permission'))
->save();
// Setup a role with just one permission.
$this->roleStorage->create(array('id' => 'one_permission'))
->save();
user_role_grant_permissions('one_permission', array('administer permissions'));
// Setup a role with multiple permissions.
$this->roleStorage->create(array('id' => 'multiple_permissions'))
->save();
user_role_grant_permissions('multiple_permissions', array('administer permissions', 'administer users', 'access user profiles'));
// Setup a user without an extra role.
$this->users[] = $account = $this->userStorage->create(['name' => $this->randomString()]);
$account->save();
// Setup a user with just the first role (so no permission beside the
// ones from the authenticated role).
$this->users[] = $account = $this->userStorage->create(array('name' => 'first_role'));
$account->addRole('no_permission');
$account->save();
// Setup a user with just the second role (so one additional permission).
$this->users[] = $account = $this->userStorage->create(array('name' => 'second_role'));
$account->addRole('one_permission');
$account->save();
// Setup a user with both the second and the third role.
$this->users[] = $account = $this->userStorage->create(array('name' => 'second_third_role'));
$account->addRole('one_permission');
$account->addRole('multiple_permissions');
$account->save();
}
}

View file

@ -0,0 +1,67 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\user\Entity\User;
use Drupal\Tests\views\Kernel\Handler\FieldFieldAccessTestBase;
/**
* Tests base field access in Views for the user entity.
*
* @group user
*/
class UserViewsFieldAccessTest extends FieldFieldAccessTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'entity_test', 'language'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->installEntitySchema('user');
}
public function testUserFields() {
ConfigurableLanguage::create([
'id' => 'es',
'name' => 'Spanish',
])->save();
ConfigurableLanguage::create([
'id' => 'fr',
'name' => 'French',
])->save();
$user = User::create([
'name' => 'test user',
'mail' => 'druplicon@drop.org',
'status' => 1,
'preferred_langcode' => 'es',
'preferred_admin_langcode' => 'fr',
'timezone' => 'ut1',
'created' => 123456,
]);
$user->save();
// @todo Expand the test coverage in https://www.drupal.org/node/2464635
$this->assertFieldAccess('user', 'uid', $user->id());
$this->assertFieldAccess('user', 'uuid', $user->uuid());
$this->assertFieldAccess('user', 'langcode', $user->language()->getName());
$this->assertFieldAccess('user', 'preferred_langcode', 'Spanish');
$this->assertFieldAccess('user', 'preferred_admin_langcode', 'French');
$this->assertFieldAccess('user', 'name', 'test user');
// $this->assertFieldAccess('user', 'mail', 'druplicon@drop.org');
$this->assertFieldAccess('user', 'timezone', 'ut1');
$this->assertFieldAccess('user', 'status', 'On');
// $this->assertFieldAccess('user', 'created', \Drupal::service('date.formatter')->format(123456));
// $this->assertFieldAccess('user', 'changed', \Drupal::service('date.formatter')->format(REQUEST_TIME));
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace Drupal\Tests\user\Unit\Menu;
use Drupal\Tests\Core\Menu\LocalTaskIntegrationTestBase;
/**
* Tests user local tasks.
*
* @group user
*/
class UserLocalTasksTest extends LocalTaskIntegrationTestBase {
protected function setUp() {
$this->directoryList = array('user' => 'core/modules/user');
parent::setUp();
}
/**
* Tests local task existence.
*
* @dataProvider getUserAdminRoutes
*/
public function testUserAdminLocalTasks($route, $expected) {
$this->assertLocalTasks($route, $expected);
}
/**
* Provides a list of routes to test.
*/
public function getUserAdminRoutes() {
return array(
array('entity.user.collection', array(array('entity.user.collection', 'user.admin_permissions', 'entity.user_role.collection'))),
array('user.admin_permissions', array(array('entity.user.collection', 'user.admin_permissions', 'entity.user_role.collection'))),
array('entity.user_role.collection', array(array('entity.user.collection', 'user.admin_permissions', 'entity.user_role.collection'))),
array('entity.user.admin_form', array(array('user.account_settings_tab'))),
);
}
/**
* Checks user listing local tasks.
*
* @dataProvider getUserLoginRoutes
*/
public function testUserLoginLocalTasks($route) {
$tasks = array(
0 => array('user.register', 'user.pass', 'user.login',),
);
$this->assertLocalTasks($route, $tasks);
}
/**
* Provides a list of routes to test.
*/
public function getUserLoginRoutes() {
return array(
array('user.login'),
array('user.register'),
array('user.pass'),
);
}
/**
* Checks user listing local tasks.
*
* @dataProvider getUserPageRoutes
*/
public function testUserPageLocalTasks($route, $subtask = array()) {
$tasks = array(
0 => array('entity.user.canonical', 'entity.user.edit_form',),
);
if ($subtask) $tasks[] = $subtask;
$this->assertLocalTasks($route, $tasks);
}
/**
* Provides a list of routes to test.
*/
public function getUserPageRoutes() {
return array(
array('entity.user.canonical'),
array('entity.user.edit_form'),
);
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace Drupal\Tests\user\Unit;
use Drupal\Core\Access\AccessResult;
use Drupal\Tests\UnitTestCase;
use Drupal\user\Access\PermissionAccessCheck;
use Symfony\Component\Routing\Route;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* @coversDefaultClass \Drupal\user\Access\PermissionAccessCheck
* @group Routing
* @group Access
*/
class PermissionAccessCheckTest extends UnitTestCase {
/**
* The tested access checker.
*
* @var \Drupal\user\Access\PermissionAccessCheck
*/
public $accessCheck;
/**
* The dependency injection container.
*
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected $container;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container = new ContainerBuilder();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
$cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
$cache_contexts_manager->reveal();
$this->container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($this->container);
$this->accessCheck = new PermissionAccessCheck();
}
/**
* Provides data for the testAccess method.
*
* @return array
*/
public function providerTestAccess() {
return [
[[], FALSE],
[['_permission' => 'allowed'], TRUE, ['user.permissions']],
[['_permission' => 'denied'], FALSE, ['user.permissions']],
[['_permission' => 'allowed+denied'], TRUE, ['user.permissions']],
[['_permission' => 'allowed+denied+other'], TRUE, ['user.permissions']],
[['_permission' => 'allowed,denied'], FALSE, ['user.permissions']],
];
}
/**
* Tests the access check method.
*
* @dataProvider providerTestAccess
* @covers ::access
*/
public function testAccess($requirements, $access, array $contexts = []) {
$access_result = AccessResult::allowedIf($access)->addCacheContexts($contexts);
$user = $this->getMock('Drupal\Core\Session\AccountInterface');
$user->expects($this->any())
->method('hasPermission')
->will($this->returnValueMap([
['allowed', TRUE],
['denied', FALSE],
['other', FALSE]
]
));
$route = new Route('', [], $requirements);
$this->assertEquals($access_result, $this->accessCheck->access($route, $user));
}
}

View file

@ -0,0 +1,463 @@
<?php
/**
* @file
* Contains \Drupal\Tests\user\Unit\PermissionHandlerTest.
*/
namespace Drupal\Tests\user\Unit;
use Drupal\Core\Extension\Extension;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\user\PermissionHandler;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamWrapper;
/**
* Tests the permission handler.
*
* @group user
*
* @coversDefaultClass \Drupal\user\PermissionHandler
*/
class PermissionHandlerTest extends UnitTestCase {
/**
* The tested permission handler.
*
* @var \Drupal\Tests\user\Unit\TestPermissionHandler|\Drupal\user\PermissionHandler
*/
protected $permissionHandler;
/**
* The mocked module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $moduleHandler;
/**
* The mocked string translation.
*
* @var \Drupal\Tests\user\Unit\TestTranslationManager
*/
protected $stringTranslation;
/**
* The mocked controller resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $controllerResolver;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->stringTranslation = new TestTranslationManager();
$this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
}
/**
* Provides an extension object for a given module with a human name.
*
* @param string $module
* The module machine name.
* @param string $name
* The module human name.
*
* @return \Drupal\Core\Extension\Extension
* The extension object.
*/
protected function mockModuleExtension($module, $name) {
$extension = new Extension($this->root, $module, "modules/$module");
$extension->info['name'] = $name;
return $extension;
}
/**
* Tests permissions provided by YML files.
*
* @covers ::__construct
* @covers ::getPermissions
* @covers ::buildPermissionsYaml
* @covers ::moduleProvidesPermissions
*/
public function testBuildPermissionsYaml() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn(array(
'module_a' => vfsStream::url('modules/module_a'),
'module_b' => vfsStream::url('modules/module_b'),
'module_c' => vfsStream::url('modules/module_c'),
));
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', "access_module_a: single_description");
mkdir($url . '/module_b');
file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
'access module b':
title: 'Access B'
description: 'bla bla'
'access module a via module b':
title: 'Access A via B'
provider: 'module_a'
EOF
);
mkdir($url . '/module_c');
file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
'access_module_c':
title: 'Access C'
description: 'bla bla'
'restrict access': TRUE
EOF
);
$modules = array('module_a', 'module_b', 'module_c');
$extensions = array(
'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
'module_b' => $this->mockModuleExtension('module_b', 'Module b'),
'module_c' => $this->mockModuleExtension('module_c', 'Module c'),
);
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('permission')
->willReturn(array());
$this->moduleHandler->expects($this->any())
->method('getModuleList')
->willReturn(array_flip($modules));
$this->controllerResolver->expects($this->never())
->method('getControllerFromDefinition');
$this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
// Setup system_rebuild_module_data().
$this->permissionHandler->setSystemRebuildModuleData($extensions);
$actual_permissions = $this->permissionHandler->getPermissions();
$this->assertPermissions($actual_permissions);
$this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_a'));
$this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_b'));
$this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_c'));
$this->assertFalse($this->permissionHandler->moduleProvidesPermissions('module_d'));
}
/**
* Tests permissions sort inside a module.
*
* @covers ::__construct
* @covers ::getPermissions
* @covers ::buildPermissionsYaml
* @covers ::sortPermissions
*/
public function testBuildPermissionsSortPerModule() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn([
'module_a' => vfsStream::url('modules/module_a'),
'module_b' => vfsStream::url('modules/module_b'),
'module_c' => vfsStream::url('modules/module_c'),
]);
$this->moduleHandler->expects($this->exactly(3))
->method('getName')
->will($this->returnValueMap([
['module_a', 'Module a'],
['module_b', 'Module b'],
['module_c', 'A Module'],
]));
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
access_module_a2: single_description2
access_module_a1: single_description1
EOF
);
mkdir($url . '/module_b');
file_put_contents($url . '/module_b/module_b.permissions.yml',
"access_module_a3: single_description"
);
mkdir($url . '/module_c');
file_put_contents($url . '/module_c/module_c.permissions.yml',
"access_module_a4: single_description"
);
$modules = ['module_a', 'module_b', 'module_c'];
$this->moduleHandler->expects($this->once())
->method('getModuleList')
->willReturn(array_flip($modules));
$permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
$actual_permissions = $permissionHandler->getPermissions();
$this->assertEquals(['access_module_a4', 'access_module_a1', 'access_module_a2', 'access_module_a3'],
array_keys($actual_permissions));
}
/**
* Tests dynamic callback permissions provided by YML files.
*
* @covers ::__construct
* @covers ::getPermissions
* @covers ::buildPermissionsYaml
*/
public function testBuildPermissionsYamlCallback() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn(array(
'module_a' => vfsStream::url('modules/module_a'),
'module_b' => vfsStream::url('modules/module_b'),
'module_c' => vfsStream::url('modules/module_c'),
));
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription'
EOF
);
mkdir($url . '/module_b');
file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider'
EOF
);
mkdir($url . '/module_c');
file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess'
EOF
);
$modules = array('module_a', 'module_b', 'module_c');
$extensions = array(
'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
'module_b' => $this->mockModuleExtension('module_b', 'Module b'),
'module_c' => $this->mockModuleExtension('module_c', 'Module c'),
);
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('permission')
->willReturn(array());
$this->moduleHandler->expects($this->any())
->method('getModuleList')
->willReturn(array_flip($modules));
$this->controllerResolver->expects($this->at(0))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription')
->willReturn(array(new TestPermissionCallbacks(), 'singleDescription'));
$this->controllerResolver->expects($this->at(1))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
->willReturn(array(new TestPermissionCallbacks(), 'titleDescription'));
$this->controllerResolver->expects($this->at(2))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider')
->willReturn(array(new TestPermissionCallbacks(), 'titleProvider'));
$this->controllerResolver->expects($this->at(3))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess')
->willReturn(array(new TestPermissionCallbacks(), 'titleDescriptionRestrictAccess'));
$this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
// Setup system_rebuild_module_data().
$this->permissionHandler->setSystemRebuildModuleData($extensions);
$actual_permissions = $this->permissionHandler->getPermissions();
$this->assertPermissions($actual_permissions);
}
/**
* Tests a YAML file containing both static permissions and a callback.
*/
public function testPermissionsYamlStaticAndCallback() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn(array(
'module_a' => vfsStream::url('modules/module_a'),
));
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
'access module a':
title: 'Access A'
description: 'bla bla'
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
EOF
);
$modules = array('module_a');
$extensions = array(
'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
);
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('permission')
->willReturn(array());
$this->moduleHandler->expects($this->any())
->method('getModuleList')
->willReturn(array_flip($modules));
$this->controllerResolver->expects($this->once())
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
->willReturn(array(new TestPermissionCallbacks(), 'titleDescription'));
$this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
// Setup system_rebuild_module_data().
$this->permissionHandler->setSystemRebuildModuleData($extensions);
$actual_permissions = $this->permissionHandler->getPermissions();
$this->assertCount(2, $actual_permissions);
$this->assertEquals($actual_permissions['access module a']['title'], 'Access A');
$this->assertEquals($actual_permissions['access module a']['provider'], 'module_a');
$this->assertEquals($actual_permissions['access module a']['description'], 'bla bla');
$this->assertEquals($actual_permissions['access module b']['title'], 'Access B');
$this->assertEquals($actual_permissions['access module b']['provider'], 'module_a');
$this->assertEquals($actual_permissions['access module b']['description'], 'bla bla');
}
/**
* Checks that the permissions are like expected.
*
* @param array $actual_permissions
* The actual permissions
*/
protected function assertPermissions(array $actual_permissions) {
$this->assertCount(4, $actual_permissions);
$this->assertEquals($actual_permissions['access_module_a']['title'], 'single_description');
$this->assertEquals($actual_permissions['access_module_a']['provider'], 'module_a');
$this->assertEquals($actual_permissions['access module b']['title'], 'Access B');
$this->assertEquals($actual_permissions['access module b']['provider'], 'module_b');
$this->assertEquals($actual_permissions['access_module_c']['title'], 'Access C');
$this->assertEquals($actual_permissions['access_module_c']['provider'], 'module_c');
$this->assertEquals($actual_permissions['access_module_c']['restrict access'], TRUE);
$this->assertEquals($actual_permissions['access module a via module b']['provider'], 'module_a');
}
}
class TestPermissionHandler extends PermissionHandler {
/**
* Test module data.
*
* @var array
*/
protected $systemModuleData;
protected function systemRebuildModuleData() {
return $this->systemModuleData;
}
public function setSystemRebuildModuleData(array $extensions) {
$this->systemModuleData = $extensions;
}
}
class TestPermissionCallbacks {
public function singleDescription() {
return array(
'access_module_a' => 'single_description'
);
}
public function titleDescription() {
return array(
'access module b' => array(
'title' => 'Access B',
'description' => 'bla bla',
),
);
}
public function titleDescriptionRestrictAccess() {
return array(
'access_module_c' => array(
'title' => 'Access C',
'description' => 'bla bla',
'restrict access' => TRUE,
),
);
}
public function titleProvider() {
return array(
'access module a via module b' => array(
'title' => 'Access A via B',
'provider' => 'module_a',
),
);
}
}
/**
* Implements a translation manager in tests.
*/
class TestTranslationManager implements TranslationInterface {
/**
* {@inheritdoc}
*/
public function translate($string, array $args = array(), array $options = array()) {
return new TranslatableMarkup($string, $args, $options, $this);
}
/**
* {@inheritdoc}
*/
public function translateString(TranslatableMarkup $translated_string) {
return $translated_string->getUntranslatedString();
}
/**
* {@inheritdoc}
*/
public function formatPlural($count, $singular, $plural, array $args = array(), array $options = array()) {
return new PluralTranslatableMarkup($count, $singular, $plural, $args, $options, $this);
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Action;
use Drupal\user\Plugin\Action\AddRoleUser;
/**
* @coversDefaultClass \Drupal\user\Plugin\Action\AddRoleUser
* @group user
*/
class AddRoleUserTest extends RoleUserTestBase {
/**
* Tests the execute method on a user with a role.
*/
public function testExecuteAddExistingRole() {
$this->account->expects($this->never())
->method('addRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(TRUE));
$config = array('rid' => 'test_role_1');
$remove_role_plugin = new AddRoleUser($config, 'user_add_role_action', array('type' => 'user'), $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
/**
* Tests the execute method on a user without a specific role.
*/
public function testExecuteAddNonExistingRole() {
$this->account->expects($this->once())
->method('addRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(FALSE));
$config = array('rid' => 'test_role_1');
$remove_role_plugin = new AddRoleUser($config, 'user_remove_role_action', array('type' => 'user'), $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Action;
use Drupal\user\Plugin\Action\RemoveRoleUser;
/**
* @coversDefaultClass \Drupal\user\Plugin\Action\RemoveRoleUser
* @group user
*/
class RemoveRoleUserTest extends RoleUserTestBase {
/**
* Tests the execute method on a user with a role.
*/
public function testExecuteRemoveExistingRole() {
$this->account->expects($this->once())
->method('removeRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(TRUE));
$config = array('rid' => 'test_role_1');
$remove_role_plugin = new RemoveRoleUser($config, 'user_remove_role_action', array('type' => 'user'), $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
/**
* Tests the execute method on a user without a specific role.
*/
public function testExecuteRemoveNonExistingRole() {
$this->account->expects($this->never())
->method('removeRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(FALSE));
$config = array('rid' => 'test_role_1');
$remove_role_plugin = new RemoveRoleUser($config, 'user_remove_role_action', array('type' => 'user'), $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Action;
use Drupal\Tests\UnitTestCase;
/**
* Provides a base class for user role action tests.
*/
abstract class RoleUserTestBase extends UnitTestCase {
/**
* The mocked account.
*
* @var \Drupal\user\UserInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $account;
/**
* The user role entity type.
*
* @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $userRoleEntityType;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->account = $this
->getMockBuilder('Drupal\user\Entity\User')
->disableOriginalConstructor()
->getMock();
$this->userRoleEntityType = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Core\Entity;
use Drupal\Tests\Core\Session\UserSessionTest;
use Drupal\user\RoleInterface;
/**
* @coversDefaultClass \Drupal\user\Entity\User
* @group user
*/
class UserTest extends UserSessionTest {
/**
* {@inheritdoc}
*/
protected function createUserSession(array $rids = array(), $authenticated = FALSE) {
$user = $this->getMockBuilder('Drupal\user\Entity\User')
->disableOriginalConstructor()
->setMethods(array('get', 'id'))
->getMock();
$user->expects($this->any())
->method('id')
// @todo Also test the uid = 1 handling.
->will($this->returnValue($authenticated ? 2 : 0));
$roles = array();
foreach ($rids as $rid) {
$roles[] = (object) array(
'target_id' => $rid,
);
}
$user->expects($this->any())
->method('get')
->with('roles')
->will($this->returnValue($roles));
return $user;
}
/**
* Tests the method getRoles exclude or include locked roles based in param.
*
* @see \Drupal\user\Entity\User::getRoles()
* @covers ::getRoles
*/
public function testUserGetRoles() {
// Anonymous user.
$user = $this->createUserSession(array());
$this->assertEquals(array(RoleInterface::ANONYMOUS_ID), $user->getRoles());
$this->assertEquals(array(), $user->getRoles(TRUE));
// Authenticated user.
$user = $this->createUserSession(array(), TRUE);
$this->assertEquals(array(RoleInterface::AUTHENTICATED_ID), $user->getRoles());
$this->assertEquals(array(), $user->getRoles(TRUE));
}
}

View file

@ -0,0 +1,309 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Validation\Constraint;
use Drupal\Tests\UnitTestCase;
use Drupal\user\Plugin\Validation\Constraint\ProtectedUserFieldConstraint;
use Drupal\user\Plugin\Validation\Constraint\ProtectedUserFieldConstraintValidator;
/**
* @coversDefaultClass \Drupal\user\Plugin\Validation\Constraint\ProtectedUserFieldConstraintValidator
* @group user
*/
class ProtectedUserFieldConstraintValidatorTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
protected function createValidator() {
// Setup mocks that don't need to change.
$unchanged_field = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$unchanged_field->expects($this->any())
->method('getValue')
->willReturn('unchanged-value');
$unchanged_account = $this->getMock('Drupal\user\UserInterface');
$unchanged_account->expects($this->any())
->method('get')
->willReturn($unchanged_field);
$user_storage = $this->getMock('Drupal\user\UserStorageInterface');
$user_storage->expects($this->any())
->method('loadUnchanged')
->willReturn($unchanged_account);
$current_user = $this->getMock('Drupal\Core\Session\AccountProxyInterface');
$current_user->expects($this->any())
->method('id')
->willReturn('current-user');
return new ProtectedUserFieldConstraintValidator($user_storage, $current_user);
}
/**
* @covers ::validate
*
* @dataProvider providerTestValidate
*/
public function testValidate($items, $expected_violation, $name = FALSE) {
$constraint = new ProtectedUserFieldConstraint();
// If a violation is expected, then the context's addViolation method will
// be called, otherwise it should not be called.
$context = $this->getMock('Symfony\Component\Validator\ExecutionContextInterface');
if ($expected_violation) {
$context->expects($this->once())
->method('addViolation')
->with($constraint->message, array('%name' => $name));
}
else {
$context->expects($this->never())
->method('addViolation');
}
$validator = $this->createValidator();
$validator->initialize($context);
$validator->validate($items, $constraint);
}
/**
* Data provider for ::testValidate().
*/
public function providerTestValidate() {
$cases = [];
// Case 1: Validation context should not be touched if no items are passed.
$cases[] = [NULL, FALSE];
// Case 2: Empty user should be ignored.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn(NULL);
$cases[] = [$items, FALSE];
// Case 3: Account flagged to skip protected user should be ignored.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$account = $this->getMock('Drupal\user\UserInterface');
$account->_skipProtectedUserFieldConstraint = TRUE;
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$cases[] = [$items, FALSE];
// Case 4: New user should be ignored.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(TRUE);
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$cases[] = [$items, FALSE];
// Case 5: Mismatching user IDs should also be ignored.
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->once())
->method('id')
->willReturn('not-current-user');
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$cases[] = [$items, FALSE];
// Case 6: Non-password fields that have not changed should be ignored.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->exactly(2))
->method('getName')
->willReturn('field_not_password');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->exactly(2))
->method('id')
->willReturn('current-user');
$account->expects($this->never())
->method('checkExistingPassword');
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$items->expects($this->once())
->method('getValue')
->willReturn('unchanged-value');
$cases[] = [$items, FALSE];
// Case 7: Password field with no value set should be ignored.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->once())
->method('getName')
->willReturn('pass');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->exactly(2))
->method('id')
->willReturn('current-user');
$account->expects($this->never())
->method('checkExistingPassword');
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$cases[] = [$items, FALSE];
// Case 8: Non-password field changed, but user has passed provided current
// password.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->exactly(2))
->method('getName')
->willReturn('field_not_password');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->exactly(2))
->method('id')
->willReturn('current-user');
$account->expects($this->once())
->method('checkExistingPassword')
->willReturn(TRUE);
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$items->expects($this->once())
->method('getValue')
->willReturn('changed-value');
$cases[] = [$items, FALSE];
// Case 9: Password field changed, current password confirmed.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->exactly(2))
->method('getName')
->willReturn('pass');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->exactly(2))
->method('id')
->willReturn('current-user');
$account->expects($this->once())
->method('checkExistingPassword')
->willReturn(TRUE);
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$items->expects($this->any())
->method('getValue')
->willReturn('changed-value');
$items->expects($this->once())
->method('__get')
->with('value')
->willReturn('changed-value');
$cases[] = [$items, FALSE];
// The below calls should result in a violation.
// Case 10: Password field changed, current password not confirmed.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->exactly(2))
->method('getName')
->willReturn('pass');
$field_definition->expects($this->any())
->method('getLabel')
->willReturn('Password');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->exactly(2))
->method('id')
->willReturn('current-user');
$account->expects($this->once())
->method('checkExistingPassword')
->willReturn(FALSE);
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$items->expects($this->once())
->method('getValue')
->willReturn('changed-value');
$items->expects($this->once())
->method('__get')
->with('value')
->willReturn('changed-value');
$cases[] = [$items, TRUE, 'Password'];
// Case 11: Non-password field changed, current password not confirmed.
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->exactly(2))
->method('getName')
->willReturn('field_not_password');
$field_definition->expects($this->any())
->method('getLabel')
->willReturn('Protected field');
$account = $this->getMock('Drupal\user\UserInterface');
$account->expects($this->once())
->method('isNew')
->willReturn(FALSE);
$account->expects($this->exactly(2))
->method('id')
->willReturn('current-user');
$account->expects($this->once())
->method('checkExistingPassword')
->willReturn(FALSE);
$items = $this->getMock('Drupal\Core\Field\FieldItemListInterface');
$items->expects($this->once())
->method('getFieldDefinition')
->willReturn($field_definition);
$items->expects($this->once())
->method('getEntity')
->willReturn($account);
$items->expects($this->once())
->method('getValue')
->willReturn('changed-value');
$cases[] = [$items, TRUE, 'Protected field'];
return $cases;
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\migrate\process;
use Drupal\user\Plugin\migrate\process\ConvertTokens;
use Drupal\Tests\migrate\Unit\process\MigrateProcessTestCase;
/**
* Tests the ConvertTokens plugin.
*
* @group user
*/
class ConvertTokensTest extends MigrateProcessTestCase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->plugin = new ConvertTokens([], 'convert_tokens', []);
}
/**
* Tests conversion of user tokens.
*/
public function testConvertTokens() {
$value = $this->plugin->transform('Account details for !username at !site', $this->migrateExecutable, $this->row, 'destinationproperty');
$this->assertEquals('Account details for [user:name] at [site:name]', $value);
}
/**
* Tests conversion of user tokens with a NULL value.
*/
public function testConvertTokensNull() {
$value = $this->plugin->transform(NULL, $this->migrateExecutable, $this->row, 'destinationproperty');
$this->assertEquals('', $value);
}
}

View file

@ -0,0 +1,93 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\views\field;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Tests\UnitTestCase;
use Drupal\user\Plugin\views\field\UserBulkForm;
/**
* @coversDefaultClass \Drupal\user\Plugin\views\field\UserBulkForm
* @group user
*/
class UserBulkFormTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
protected function tearDown() {
parent::tearDown();
$container = new ContainerBuilder();
\Drupal::setContainer($container);
}
/**
* Tests the constructor assignment of actions.
*/
public function testConstructor() {
$actions = array();
for ($i = 1; $i <= 2; $i++) {
$action = $this->getMock('\Drupal\system\ActionConfigEntityInterface');
$action->expects($this->any())
->method('getType')
->will($this->returnValue('user'));
$actions[$i] = $action;
}
$action = $this->getMock('\Drupal\system\ActionConfigEntityInterface');
$action->expects($this->any())
->method('getType')
->will($this->returnValue('node'));
$actions[] = $action;
$entity_storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
$entity_storage->expects($this->any())
->method('loadMultiple')
->will($this->returnValue($actions));
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$entity_manager->expects($this->once())
->method('getStorage')
->with('action')
->will($this->returnValue($entity_storage));
$language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
$views_data = $this->getMockBuilder('Drupal\views\ViewsData')
->disableOriginalConstructor()
->getMock();
$views_data->expects($this->any())
->method('get')
->with('users')
->will($this->returnValue(array('table' => array('entity type' => 'user'))));
$container = new ContainerBuilder();
$container->set('views.views_data', $views_data);
$container->set('string_translation', $this->getStringTranslationStub());
\Drupal::setContainer($container);
$storage = $this->getMock('Drupal\views\ViewEntityInterface');
$storage->expects($this->any())
->method('get')
->with('base_table')
->will($this->returnValue('users'));
$executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
->disableOriginalConstructor()
->getMock();
$executable->storage = $storage;
$display = $this->getMockBuilder('Drupal\views\Plugin\views\display\DisplayPluginBase')
->disableOriginalConstructor()
->getMock();
$definition['title'] = '';
$options = array();
$user_bulk_form = new UserBulkForm(array(), 'user_bulk_form', $definition, $entity_manager, $language_manager);
$user_bulk_form->init($executable, $display, $options);
$this->assertAttributeEquals(array_slice($actions, 0, -1, TRUE), 'actions', $user_bulk_form);
}
}

View file

@ -0,0 +1,280 @@
<?php
namespace Drupal\Tests\user\Unit;
use Drupal\Tests\UnitTestCase;
use Drupal\user\PrivateTempStore;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* @coversDefaultClass \Drupal\user\PrivateTempStore
* @group user
*/
class PrivateTempStoreTest extends UnitTestCase {
/**
* The mock key value expirable backend.
*
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $keyValue;
/**
* The mock lock backend.
*
* @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $lock;
/**
* The user temp store.
*
* @var \Drupal\user\PrivateTempStore
*/
protected $tempStore;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $currentUser;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* A tempstore object belonging to the owner.
*
* @var \stdClass
*/
protected $ownObject;
/**
* A tempstore object not belonging to the owner.
*
* @var \stdClass
*/
protected $otherObject;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->keyValue = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
$this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
$this->currentUser = $this->getMock('Drupal\Core\Session\AccountProxyInterface');
$this->currentUser->expects($this->any())
->method('id')
->willReturn(1);
$this->requestStack = new RequestStack();
$request = Request::createFromGlobals();
$this->requestStack->push($request);
$this->tempStore = new PrivateTempStore($this->keyValue, $this->lock, $this->currentUser, $this->requestStack, 604800);
$this->ownObject = (object) array(
'data' => 'test_data',
'owner' => $this->currentUser->id(),
'updated' => (int) $request->server->get('REQUEST_TIME'),
);
// Clone the object but change the owner.
$this->otherObject = clone $this->ownObject;
$this->otherObject->owner = 2;
}
/**
* Tests the get() method.
*
* @covers ::get
*/
public function testGet() {
$this->keyValue->expects($this->at(0))
->method('get')
->with('1:test_2')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->at(1))
->method('get')
->with('1:test')
->will($this->returnValue($this->ownObject));
$this->keyValue->expects($this->at(2))
->method('get')
->with('1:test')
->will($this->returnValue($this->otherObject));
$this->assertNull($this->tempStore->get('test_2'));
$this->assertSame($this->ownObject->data, $this->tempStore->get('test'));
$this->assertNull($this->tempStore->get('test'));
}
/**
* Tests the set() method with no lock available.
*
* @covers ::set
* @expectedException \Drupal\user\TempStoreException
*/
public function testSetWithNoLockAvailable() {
$this->lock->expects($this->at(0))
->method('acquire')
->with('1:test')
->will($this->returnValue(FALSE));
$this->lock->expects($this->at(1))
->method('wait')
->with('1:test');
$this->lock->expects($this->at(2))
->method('acquire')
->with('1:test')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->once())
->method('getCollectionName');
$this->tempStore->set('test', 'value');
}
/**
* Tests a successful set() call.
*
* @covers ::set
*/
public function testSet() {
$this->lock->expects($this->once())
->method('acquire')
->with('1:test')
->will($this->returnValue(TRUE));
$this->lock->expects($this->never())
->method('wait');
$this->lock->expects($this->once())
->method('release')
->with('1:test');
$this->keyValue->expects($this->once())
->method('setWithExpire')
->with('1:test', $this->ownObject, 604800);
$this->tempStore->set('test', 'test_data');
}
/**
* Tests the getMetadata() method.
*
* @covers ::getMetadata
*/
public function testGetMetadata() {
$this->keyValue->expects($this->at(0))
->method('get')
->with('1:test')
->will($this->returnValue($this->ownObject));
$this->keyValue->expects($this->at(1))
->method('get')
->with('1:test')
->will($this->returnValue(FALSE));
$metadata = $this->tempStore->getMetadata('test');
$this->assertObjectHasAttribute('owner', $metadata);
// Data should get removed.
$this->assertObjectNotHasAttribute('data', $metadata);
$this->assertNull($this->tempStore->getMetadata('test'));
}
/**
* Tests the locking in the delete() method.
*
* @covers ::delete
*/
public function testDeleteLocking() {
$this->keyValue->expects($this->once())
->method('get')
->with('1:test')
->will($this->returnValue($this->ownObject));
$this->lock->expects($this->once())
->method('acquire')
->with('1:test')
->will($this->returnValue(TRUE));
$this->lock->expects($this->never())
->method('wait');
$this->lock->expects($this->once())
->method('release')
->with('1:test');
$this->keyValue->expects($this->once())
->method('delete')
->with('1:test');
$this->assertTrue($this->tempStore->delete('test'));
}
/**
* Tests the delete() method with no lock available.
*
* @covers ::delete
* @expectedException \Drupal\user\TempStoreException
*/
public function testDeleteWithNoLockAvailable() {
$this->keyValue->expects($this->once())
->method('get')
->with('1:test')
->will($this->returnValue($this->ownObject));
$this->lock->expects($this->at(0))
->method('acquire')
->with('1:test')
->will($this->returnValue(FALSE));
$this->lock->expects($this->at(1))
->method('wait')
->with('1:test');
$this->lock->expects($this->at(2))
->method('acquire')
->with('1:test')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->once())
->method('getCollectionName');
$this->tempStore->delete('test');
}
/**
* Tests the delete() method.
*
* @covers ::delete
*/
public function testDelete() {
$this->lock->expects($this->once())
->method('acquire')
->with('1:test_2')
->will($this->returnValue(TRUE));
$this->keyValue->expects($this->at(0))
->method('get')
->with('1:test_1')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->at(1))
->method('get')
->with('1:test_2')
->will($this->returnValue($this->ownObject));
$this->keyValue->expects($this->at(2))
->method('delete')
->with('1:test_2');
$this->keyValue->expects($this->at(3))
->method('get')
->with('1:test_3')
->will($this->returnValue($this->otherObject));
$this->assertTrue($this->tempStore->delete('test_1'));
$this->assertTrue($this->tempStore->delete('test_2'));
$this->assertFalse($this->tempStore->delete('test_3'));
}
}

View file

@ -0,0 +1,352 @@
<?php
namespace Drupal\Tests\user\Unit;
use Drupal\Tests\UnitTestCase;
use Drupal\user\SharedTempStore;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* @coversDefaultClass \Drupal\user\SharedTempStore
* @group user
*/
class SharedTempStoreTest extends UnitTestCase {
/**
* The mock key value expirable backend.
*
* @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $keyValue;
/**
* The mock lock backend.
*
* @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $lock;
/**
* The user temp store.
*
* @var \Drupal\user\SharedTempStore
*/
protected $tempStore;
/**
* The owner used in this test.
*
* @var int
*/
protected $owner = 1;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* A tempstore object belonging to the owner.
*
* @var \stdClass
*/
protected $ownObject;
/**
* A tempstore object not belonging to the owner.
*
* @var \stdClass
*/
protected $otherObject;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->keyValue = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
$this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
$this->requestStack = new RequestStack();
$request = Request::createFromGlobals();
$this->requestStack->push($request);
$this->tempStore = new SharedTempStore($this->keyValue, $this->lock, $this->owner, $this->requestStack, 604800);
$this->ownObject = (object) array(
'data' => 'test_data',
'owner' => $this->owner,
'updated' => (int) $request->server->get('REQUEST_TIME'),
);
// Clone the object but change the owner.
$this->otherObject = clone $this->ownObject;
$this->otherObject->owner = 2;
}
/**
* @covers ::get
*/
public function testGet() {
$this->keyValue->expects($this->at(0))
->method('get')
->with('test_2')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->at(1))
->method('get')
->with('test')
->will($this->returnValue($this->ownObject));
$this->assertNull($this->tempStore->get('test_2'));
$this->assertSame($this->ownObject->data, $this->tempStore->get('test'));
}
/**
* Tests the getIfOwner() method.
*
* @covers ::getIfOwner
*/
public function testGetIfOwner() {
$this->keyValue->expects($this->at(0))
->method('get')
->with('test_2')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->at(1))
->method('get')
->with('test')
->will($this->returnValue($this->ownObject));
$this->keyValue->expects($this->at(2))
->method('get')
->with('test')
->will($this->returnValue($this->otherObject));
$this->assertNull($this->tempStore->getIfOwner('test_2'));
$this->assertSame($this->ownObject->data, $this->tempStore->getIfOwner('test'));
$this->assertNull($this->tempStore->getIfOwner('test'));
}
/**
* Tests the set() method with no lock available.
*
* @covers ::set
* @expectedException \Drupal\user\TempStoreException
*/
public function testSetWithNoLockAvailable() {
$this->lock->expects($this->at(0))
->method('acquire')
->with('test')
->will($this->returnValue(FALSE));
$this->lock->expects($this->at(1))
->method('wait')
->with('test');
$this->lock->expects($this->at(2))
->method('acquire')
->with('test')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->once())
->method('getCollectionName');
$this->tempStore->set('test', 'value');
}
/**
* Tests a successful set() call.
*
* @covers ::set
*/
public function testSet() {
$this->lock->expects($this->once())
->method('acquire')
->with('test')
->will($this->returnValue(TRUE));
$this->lock->expects($this->never())
->method('wait');
$this->lock->expects($this->once())
->method('release')
->with('test');
$this->keyValue->expects($this->once())
->method('setWithExpire')
->with('test', $this->ownObject, 604800);
$this->tempStore->set('test', 'test_data');
}
/**
* Tests the setIfNotExists() methods.
*
* @covers ::setIfNotExists
*/
public function testSetIfNotExists() {
$this->keyValue->expects($this->once())
->method('setWithExpireIfNotExists')
->with('test', $this->ownObject, 604800)
->will($this->returnValue(TRUE));
$this->assertTrue($this->tempStore->setIfNotExists('test', 'test_data'));
}
/**
* Tests the setIfOwner() method when no key exists.
*
* @covers ::setIfOwner
*/
public function testSetIfOwnerWhenNotExists() {
$this->keyValue->expects($this->once())
->method('setWithExpireIfNotExists')
->will($this->returnValue(TRUE));
$this->assertTrue($this->tempStore->setIfOwner('test', 'test_data'));
}
/**
* Tests the setIfOwner() method when a key already exists but no object.
*
* @covers ::setIfOwner
*/
public function testSetIfOwnerNoObject() {
$this->keyValue->expects($this->once())
->method('setWithExpireIfNotExists')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->once())
->method('get')
->with('test')
->will($this->returnValue(FALSE));
$this->assertFalse($this->tempStore->setIfOwner('test', 'test_data'));
}
/**
* Tests the setIfOwner() method with matching and non matching owners.
*
* @covers ::setIfOwner
*/
public function testSetIfOwner() {
$this->lock->expects($this->once())
->method('acquire')
->with('test')
->will($this->returnValue(TRUE));
$this->keyValue->expects($this->exactly(2))
->method('setWithExpireIfNotExists')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->exactly(2))
->method('get')
->with('test')
->will($this->onConsecutiveCalls($this->ownObject, $this->otherObject));
$this->assertTrue($this->tempStore->setIfOwner('test', 'test_data'));
$this->assertFalse($this->tempStore->setIfOwner('test', 'test_data'));
}
/**
* Tests the getMetadata() method.
*
* @covers ::getMetadata
*/
public function testGetMetadata() {
$this->keyValue->expects($this->at(0))
->method('get')
->with('test')
->will($this->returnValue($this->ownObject));
$this->keyValue->expects($this->at(1))
->method('get')
->with('test')
->will($this->returnValue(FALSE));
$metadata = $this->tempStore->getMetadata('test');
$this->assertObjectHasAttribute('owner', $metadata);
// Data should get removed.
$this->assertObjectNotHasAttribute('data', $metadata);
$this->assertNull($this->tempStore->getMetadata('test'));
}
/**
* Tests the delete() method.
*
* @covers ::delete
*/
public function testDelete() {
$this->lock->expects($this->once())
->method('acquire')
->with('test')
->will($this->returnValue(TRUE));
$this->lock->expects($this->never())
->method('wait');
$this->lock->expects($this->once())
->method('release')
->with('test');
$this->keyValue->expects($this->once())
->method('delete')
->with('test');
$this->tempStore->delete('test');
}
/**
* Tests the delete() method with no lock available.
*
* @covers ::delete
* @expectedException \Drupal\user\TempStoreException
*/
public function testDeleteWithNoLockAvailable() {
$this->lock->expects($this->at(0))
->method('acquire')
->with('test')
->will($this->returnValue(FALSE));
$this->lock->expects($this->at(1))
->method('wait')
->with('test');
$this->lock->expects($this->at(2))
->method('acquire')
->with('test')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->once())
->method('getCollectionName');
$this->tempStore->delete('test');
}
/**
* Tests the deleteIfOwner() method.
*
* @covers ::deleteIfOwner
*/
public function testDeleteIfOwner() {
$this->lock->expects($this->once())
->method('acquire')
->with('test_2')
->will($this->returnValue(TRUE));
$this->keyValue->expects($this->at(0))
->method('get')
->with('test_1')
->will($this->returnValue(FALSE));
$this->keyValue->expects($this->at(1))
->method('get')
->with('test_2')
->will($this->returnValue($this->ownObject));
$this->keyValue->expects($this->at(2))
->method('delete')
->with('test_2');
$this->keyValue->expects($this->at(3))
->method('get')
->with('test_3')
->will($this->returnValue($this->otherObject));
$this->assertTrue($this->tempStore->deleteIfOwner('test_1'));
$this->assertTrue($this->tempStore->deleteIfOwner('test_2'));
$this->assertFalse($this->tempStore->deleteIfOwner('test_3'));
}
}

View file

@ -0,0 +1,418 @@
<?php
namespace Drupal\Tests\user\Unit;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Drupal\Core\DependencyInjection\Container;
use Drupal\Tests\UnitTestCase;
use Drupal\user\UserAccessControlHandler;
/**
* Tests the user access controller.
*
* @group Drupal
* @group User
*
* @coversDefaultClass \Drupal\user\UserAccessControlHandler
*/
class UserAccessControlHandlerTest extends UnitTestCase {
/**
* The user access controller to test.
*
* @var \Drupal\user\UserAccessControlHandler
*/
protected $accessControlHandler;
/**
* The mock user account with view access.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $viewer;
/**
* The mock user account that is able to change their own account name.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $owner;
/**
* The mock administrative test user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $admin;
/**
* The mocked test field items.
*
* @var \Drupal\Core\Field\FieldItemList
*/
protected $items;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
$cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
$cache_contexts_manager->reveal();
$container = new Container();
$container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($container);
$this->viewer = $this->getMock('\Drupal\Core\Session\AccountInterface');
$this->viewer
->expects($this->any())
->method('hasPermission')
->will($this->returnValue(FALSE));
$this->viewer
->expects($this->any())
->method('id')
->will($this->returnValue(1));
$this->owner = $this->getMock('\Drupal\Core\Session\AccountInterface');
$this->owner
->expects($this->any())
->method('hasPermission')
->will($this->returnValueMap(array(
array('administer users', FALSE),
array('change own username', TRUE),
)));
$this->owner
->expects($this->any())
->method('id')
->will($this->returnValue(2));
$this->admin = $this->getMock('\Drupal\Core\Session\AccountInterface');
$this->admin
->expects($this->any())
->method('hasPermission')
->will($this->returnValue(TRUE));
$entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
$this->accessControlHandler = new UserAccessControlHandler($entity_type);
$module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$module_handler->expects($this->any())
->method('getImplementations')
->will($this->returnValue(array()));
$this->accessControlHandler->setModuleHandler($module_handler);
$this->items = $this->getMockBuilder('Drupal\Core\Field\FieldItemList')
->disableOriginalConstructor()
->getMock();
$this->items
->expects($this->any())
->method('defaultAccess')
->will($this->returnValue(AccessResult::allowed()));
}
/**
* Asserts correct field access grants for a field.
*/
public function assertFieldAccess($field, $viewer, $target, $view, $edit) {
$field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
$field_definition->expects($this->any())
->method('getName')
->will($this->returnValue($field));
$this->items
->expects($this->any())
->method('getEntity')
->will($this->returnValue($this->{$target}));
foreach (array('view' => $view, 'edit' => $edit) as $operation => $result) {
$result_text = !isset($result) ? 'null' : ($result ? 'true' : 'false');
$message = "User '$field' field access returns '$result_text' with operation '$operation' for '$viewer' accessing '$target'";
$this->assertSame($result, $this->accessControlHandler->fieldAccess($operation, $field_definition, $this->{$viewer}, $this->items), $message);
}
}
/**
* Ensures user name access is working properly.
*
* @dataProvider userNameProvider
*/
public function testUserNameAccess($viewer, $target, $view, $edit) {
$this->assertFieldAccess('name', $viewer, $target, $view, $edit);
}
/**
* Provides test data for estUserNameAccess().
*/
public function userNameProvider() {
$name_access = array(
// The viewer user is allowed to see user names on all accounts.
array(
'viewer' => 'viewer',
'target' => 'viewer',
'view' => TRUE,
'edit' => FALSE,
),
array(
'viewer' => 'owner',
'target' => 'viewer',
'view' => TRUE,
'edit' => FALSE,
),
array(
'viewer' => 'viewer',
'target' => 'owner',
'view' => TRUE,
'edit' => FALSE,
),
// The owner user is allowed to change its own user name.
array(
'viewer' => 'owner',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
),
// The users-administrator user has full access.
array(
'viewer' => 'admin',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
),
);
return $name_access;
}
/**
* Tests that private user settings cannot be viewed by other users.
*
* @dataProvider hiddenUserSettingsProvider
*/
public function testHiddenUserSettings($field, $viewer, $target, $view, $edit) {
$this->assertFieldAccess($field, $viewer, $target, $view, $edit);
}
/**
* Provides test data for testHiddenUserSettings().
*/
public function hiddenUserSettingsProvider() {
$access_info = array();
$fields = array(
'preferred_langcode',
'preferred_admin_langcode',
'timezone',
'mail',
);
foreach ($fields as $field) {
$access_info[] = array(
'field' => $field,
'viewer' => 'viewer',
'target' => 'viewer',
'view' => TRUE,
'edit' => TRUE,
);
$access_info[] = array(
'field' => $field,
'viewer' => 'viewer',
'target' => 'owner',
'view' => FALSE,
// Anyone with edit access to the user can also edit these fields. In
// reality edit access will already be checked on entity level and the
// user without view access will typically not be able to edit.
'edit' => TRUE,
);
$access_info[] = array(
'field' => $field,
'viewer' => 'owner',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
);
$access_info[] = array(
'field' => $field,
'viewer' => 'admin',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
);
}
return $access_info;
}
/**
* Tests that private user settings cannot be viewed by other users.
*
* @dataProvider adminFieldAccessProvider
*/
public function testAdminFieldAccess($field, $viewer, $target, $view, $edit) {
$this->assertFieldAccess($field, $viewer, $target, $view, $edit);
}
/**
* Provides test data for testAdminFieldAccess().
*/
public function adminFieldAccessProvider() {
$access_info = array();
$fields = array(
'roles',
'status',
'access',
'login',
'init',
);
foreach ($fields as $field) {
$access_info[] = array(
'field' => $field,
'viewer' => 'viewer',
'target' => 'viewer',
'view' => FALSE,
'edit' => FALSE,
);
$access_info[] = array(
'field' => $field,
'viewer' => 'viewer',
'target' => 'owner',
'view' => FALSE,
'edit' => FALSE,
);
$access_info[] = array(
'field' => $field,
'viewer' => 'admin',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
);
}
return $access_info;
}
/**
* Tests that passwords cannot be viewed, just edited.
*
* @dataProvider passwordAccessProvider
*/
public function testPasswordAccess($viewer, $target, $view, $edit) {
$this->assertFieldAccess('pass', $viewer, $target, $view, $edit);
}
/**
* Provides test data for passwordAccessProvider().
*/
public function passwordAccessProvider() {
$pass_access = array(
array(
'viewer' => 'viewer',
'target' => 'viewer',
'view' => FALSE,
'edit' => TRUE,
),
array(
'viewer' => 'viewer',
'target' => 'owner',
'view' => FALSE,
// Anyone with edit access to the user can also edit these fields. In
// reality edit access will already be checked on entity level and the
// user without view access will typically not be able to edit.
'edit' => TRUE,
),
array(
'viewer' => 'owner',
'target' => 'viewer',
'view' => FALSE,
'edit' => TRUE,
),
array(
'viewer' => 'admin',
'target' => 'owner',
'view' => FALSE,
'edit' => TRUE,
),
);
return $pass_access;
}
/**
* Tests the user created field access.
*
* @dataProvider createdAccessProvider
*/
public function testCreatedAccess($viewer, $target, $view, $edit) {
$this->assertFieldAccess('created', $viewer, $target, $view, $edit);
}
/**
* Provides test data for testCreatedAccess().
*/
public function createdAccessProvider() {
$created_access = array(
array(
'viewer' => 'viewer',
'target' => 'viewer',
'view' => TRUE,
'edit' => FALSE,
),
array(
'viewer' => 'owner',
'target' => 'viewer',
'view' => TRUE,
'edit' => FALSE,
),
array(
'viewer' => 'admin',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
),
);
return $created_access;
}
/**
* Tests access to a non-existing base field.
*
* @dataProvider NonExistingFieldAccessProvider
*/
public function testNonExistingFieldAccess($viewer, $target, $view, $edit) {
// By default everyone has access to all fields that do not have explicit
// access control.
// @see EntityAccessControlHandler::checkFieldAccess()
$this->assertFieldAccess('some_non_existing_field', $viewer, $target, $view, $edit);
}
/**
* Provides test data for testNonExistingFieldAccess().
*/
public function NonExistingFieldAccessProvider() {
$created_access = array(
array(
'viewer' => 'viewer',
'target' => 'viewer',
'view' => TRUE,
'edit' => TRUE,
),
array(
'viewer' => 'owner',
'target' => 'viewer',
'view' => TRUE,
'edit' => TRUE,
),
array(
'viewer' => 'admin',
'target' => 'owner',
'view' => TRUE,
'edit' => TRUE,
),
);
return $created_access;
}
}

View file

@ -0,0 +1,221 @@
<?php
namespace Drupal\Tests\user\Unit;
use Drupal\Tests\UnitTestCase;
use Drupal\user\UserAuth;
/**
* @coversDefaultClass \Drupal\user\UserAuth
* @group user
*/
class UserAuthTest extends UnitTestCase {
/**
* The mock user storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $userStorage;
/**
* The mocked password service.
*
* @var \Drupal\Core\Password\PasswordInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $passwordService;
/**
* The mock user.
*
* @var \Drupal\user\Entity\User|\PHPUnit_Framework_MockObject_MockObject
*/
protected $testUser;
/**
* The user auth object under test.
*
* @var \Drupal\user\UserAuth
*/
protected $userAuth;
/**
* The test username.
*
* @var string
*/
protected $username = 'test_user';
/**
* The test password.
*
* @var string
*/
protected $password = 'password';
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->userStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$entity_manager->expects($this->any())
->method('getStorage')
->with('user')
->will($this->returnValue($this->userStorage));
$this->passwordService = $this->getMock('Drupal\Core\Password\PasswordInterface');
$this->testUser = $this->getMockBuilder('Drupal\user\Entity\User')
->disableOriginalConstructor()
->setMethods(array('id', 'setPassword', 'save', 'getPassword'))
->getMock();
$this->userAuth = new UserAuth($entity_manager, $this->passwordService);
}
/**
* Tests failing authentication with missing credential parameters.
*
* @covers ::authenticate
*
* @dataProvider providerTestAuthenticateWithMissingCredentials
*/
public function testAuthenticateWithMissingCredentials($username, $password) {
$this->userStorage->expects($this->never())
->method('loadByProperties');
$this->assertFalse($this->userAuth->authenticate($username, $password));
}
/**
* Data provider for testAuthenticateWithMissingCredentials().
*
* @return array
*/
public function providerTestAuthenticateWithMissingCredentials() {
return array(
array(NULL, NULL),
array(NULL, ''),
array('', NULL),
array('', ''),
);
}
/**
* Tests the authenticate method with no account returned.
*
* @covers ::authenticate
*/
public function testAuthenticateWithNoAccountReturned() {
$this->userStorage->expects($this->once())
->method('loadByProperties')
->with(array('name' => $this->username))
->will($this->returnValue(array()));
$this->assertFalse($this->userAuth->authenticate($this->username, $this->password));
}
/**
* Tests the authenticate method with an incorrect password.
*
* @covers ::authenticate
*/
public function testAuthenticateWithIncorrectPassword() {
$this->userStorage->expects($this->once())
->method('loadByProperties')
->with(array('name' => $this->username))
->will($this->returnValue(array($this->testUser)));
$this->passwordService->expects($this->once())
->method('check')
->with($this->password, $this->testUser->getPassword())
->will($this->returnValue(FALSE));
$this->assertFalse($this->userAuth->authenticate($this->username, $this->password));
}
/**
* Tests the authenticate method with a correct password.
*
* @covers ::authenticate
*/
public function testAuthenticateWithCorrectPassword() {
$this->testUser->expects($this->once())
->method('id')
->will($this->returnValue(1));
$this->userStorage->expects($this->once())
->method('loadByProperties')
->with(array('name' => $this->username))
->will($this->returnValue(array($this->testUser)));
$this->passwordService->expects($this->once())
->method('check')
->with($this->password, $this->testUser->getPassword())
->will($this->returnValue(TRUE));
$this->assertsame(1, $this->userAuth->authenticate($this->username, $this->password));
}
/**
* Tests the authenticate method with a correct password.
*
* We discovered in https://www.drupal.org/node/2563751 that logging in with a
* password that is literally "0" was not possible. This test ensures that
* this regression can't happen again.
*
* @covers ::authenticate
*/
public function testAuthenticateWithZeroPassword() {
$this->testUser->expects($this->once())
->method('id')
->will($this->returnValue(2));
$this->userStorage->expects($this->once())
->method('loadByProperties')
->with(array('name' => $this->username))
->will($this->returnValue(array($this->testUser)));
$this->passwordService->expects($this->once())
->method('check')
->with(0, 0)
->will($this->returnValue(TRUE));
$this->assertsame(2, $this->userAuth->authenticate($this->username, 0));
}
/**
* Tests the authenticate method with a correct password and new password hash.
*
* @covers ::authenticate
*/
public function testAuthenticateWithCorrectPasswordAndNewPasswordHash() {
$this->testUser->expects($this->once())
->method('id')
->will($this->returnValue(1));
$this->testUser->expects($this->once())
->method('setPassword')
->with($this->password);
$this->testUser->expects($this->once())
->method('save');
$this->userStorage->expects($this->once())
->method('loadByProperties')
->with(array('name' => $this->username))
->will($this->returnValue(array($this->testUser)));
$this->passwordService->expects($this->once())
->method('check')
->with($this->password, $this->testUser->getPassword())
->will($this->returnValue(TRUE));
$this->passwordService->expects($this->once())
->method('needsRehash')
->with($this->testUser->getPassword())
->will($this->returnValue(TRUE));
$this->assertsame(1, $this->userAuth->authenticate($this->username, $this->password));
}
}

View file

@ -0,0 +1,81 @@
<?php
namespace Drupal\Tests\user\Unit\Views\Argument;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Tests\UnitTestCase;
use Drupal\user\Entity\Role;
use Drupal\user\Plugin\views\argument\RolesRid;
/**
* @coversDefaultClass \Drupal\user\Plugin\views\argument\RolesRid
* @group user
*/
class RolesRidTest extends UnitTestCase {
/**
* Tests the titleQuery method.
*
* @covers ::titleQuery
*/
public function testTitleQuery() {
$role1 = new Role(array(
'id' => 'test_rid_1',
'label' => 'test rid 1'
), 'user_role');
$role2 = new Role(array(
'id' => 'test_rid_2',
'label' => 'test <strong>rid 2</strong>',
), 'user_role');
// Creates a stub entity storage;
$role_storage = $this->getMockForAbstractClass('Drupal\Core\Entity\EntityStorageInterface');
$role_storage->expects($this->any())
->method('loadMultiple')
->will($this->returnValueMap(array(
array(array(), array()),
array(array('test_rid_1'), array('test_rid_1' => $role1)),
array(array('test_rid_1', 'test_rid_2'), array('test_rid_1' => $role1, 'test_rid_2' => $role2)),
)));
$entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
$entity_type->expects($this->any())
->method('getKey')
->with('label')
->will($this->returnValue('label'));
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
$entity_manager->expects($this->any())
->method('getDefinition')
->with($this->equalTo('user_role'))
->will($this->returnValue($entity_type));
$entity_manager
->expects($this->once())
->method('getStorage')
->with($this->equalTo('user_role'))
->will($this->returnValue($role_storage));
// @todo \Drupal\Core\Entity\Entity::entityType() uses a global call to
// entity_get_info(), which in turn wraps \Drupal::entityManager(). Set
// the entity manager until this is fixed.
$container = new ContainerBuilder();
$container->set('entity.manager', $entity_manager);
\Drupal::setContainer($container);
$roles_rid_argument = new RolesRid(array(), 'user__roles_rid', array(), $entity_manager);
$roles_rid_argument->value = array();
$titles = $roles_rid_argument->titleQuery();
$this->assertEquals(array(), $titles);
$roles_rid_argument->value = array('test_rid_1');
$titles = $roles_rid_argument->titleQuery();
$this->assertEquals(array('test rid 1'), $titles);
$roles_rid_argument->value = array('test_rid_1', 'test_rid_2');
$titles = $roles_rid_argument->titleQuery();
$this->assertEquals(array('test rid 1', 'test <strong>rid 2</strong>'), $titles);
}
}

View file

@ -0,0 +1,26 @@
{#
/**
* @file
* Theme override for testing the presence of all user data.
*
* This template is used when viewing a registered user's page,
* e.g., example.com/user/123. 123 being the user's ID.
*
* Available variables:
* - content: A list of content items. Use 'content' to print all content, or
* print a subset such as 'content.field_example'. Fields attached to a user
* such as 'user_picture' are available as 'content.user_picture'.
* - attributes: HTML attributes for the container element.
* - user: A Drupal User entity.
*
* @see template_preprocess_user()
*/
#}
<article{{ attributes.addClass('profile') }}>
{% if content %}
{{ content }}
{% endif %}
{% if user %}
<p>{{ user.mail.value }}</p>
{% endif %}
</article>

View file

@ -0,0 +1,5 @@
name: 'User Test theme'
type: theme
description: 'Theme for testing the available fields in user twig template'
version: VERSION
core: 8.x