CSC/ECE 517 Fall 2023 - E2384. Reimplement user controller.rb, user.rb and its child classes: Difference between revisions
No edit summary |
|||
(11 intermediate revisions by 2 users not shown) | |||
Line 11: | Line 11: | ||
* Reimplement the search_users, find_user methods in user.rb | * Reimplement the search_users, find_user methods in user.rb | ||
* Reimplement the | * Reimplement the list, paginate_list functionality in users_controller.rb | ||
* Write thorough RSpec tests for the newly implemented functionalities | * Write thorough RSpec tests for the newly implemented functionalities | ||
Line 17: | Line 17: | ||
* Reimplement methods pertaining to controller.rb, user.rb and it's associated child classes. More specifically reimplement search_users, find_user methods in user.rb. | * Reimplement methods pertaining to controller.rb, user.rb and it's associated child classes. More specifically reimplement search_users, find_user methods in user.rb. | ||
* Reimplement the | * Reimplement the list, paginate_list functionality in users_controller.rb. | ||
* Ensure proper naming of the methods, variables. | * Ensure proper naming of the methods, variables. | ||
* Incorporate suggestions from project3. | * Incorporate suggestions from project3. | ||
Line 39: | Line 39: | ||
==== Revised UsersController.rb: ==== | ==== Revised UsersController.rb: ==== | ||
# '''list Action:''' | # '''list Action:''' | ||
Line 59: | Line 55: | ||
# '''UsersController.rb Tests:''' | # '''UsersController.rb Tests:''' | ||
## Tests for the 'list' and 'paginate_list' action will check that it correctly paginates the list of users. | ## Tests for the 'list' and 'paginate_list' action will check that it correctly paginates the list of users. | ||
Line 79: | Line 74: | ||
|- | |- | ||
|3 | |3 | ||
|Reimplement <code>list</code> action in UsersController.rb | |Reimplement <code>list</code> action in UsersController.rb | ||
|Done | |Done | ||
|This action will be updated to handle listing of users. | |This action will be updated to handle listing of users. | ||
|- | |- | ||
| | |4 | ||
|Reimplement <code>paginate_list</code> action in UsersController.rb | |Reimplement <code>paginate_list</code> action in UsersController.rb | ||
|Done | |Done | ||
|This action will be updated to handle paginated listing of users. | |This action will be updated to handle paginated listing of users. | ||
|- | |- | ||
| | |5 | ||
|Write RSpec tests for User.rb | |Write RSpec tests for User.rb | ||
|Done | |Done | ||
|New tests will be written for the `search_users` and `find_user` methods. | |New tests will be written for the `search_users` and `find_user` methods. | ||
|- | |- | ||
| | |6 | ||
|Write RSpec tests for UsersController.rb | |Write RSpec tests for UsersController.rb | ||
|Done | |Done | ||
Line 123: | Line 113: | ||
| 2.2 || Scenario 2: Test locate user by email | | 2.2 || Scenario 2: Test locate user by email | ||
|- | |- | ||
| 3 | | 3 || <strong>list and paginate_list method in user_controller.rb</strong> | ||
|- | |- | ||
| | | 3.1 || Scenario 1: checks that list and paginate_list does not fail with controller | ||
|- | |- | ||
| | | 3.2 || Scenario 2: checks that list and paginate_list does not fail with post | ||
|} | |} | ||
Line 163: | Line 143: | ||
=== Code === | === Code === | ||
The search_users method accepts three parameters: user_id, | The search_users method accepts three parameters: user_id, key, and search_by. If a valid user_id is provided, the method returns an array containing the user with that specific user_id. | ||
In cases where user_id is empty or invalid, the method performs a search based on the provided | In cases where user_id is empty or invalid, the method performs a search based on the provided key and search_by parameters. | ||
To prevent SQL injection, the method validates search_by against a predefined set of acceptable fields, including 'name', 'full_name', 'email', and 'role'. The search is then conducted using a LIKE query on the specified field, ordering the results by the user's name. | To prevent SQL injection, the method validates search_by against a predefined set of acceptable fields, including 'name', 'full_name', 'email', and 'role'. The search is then conducted using a LIKE query on the specified field, ordering the results by the user's name. | ||
Line 170: | Line 150: | ||
<source lang="ruby"> | <source lang="ruby"> | ||
def self.search_users(user_id, | def self.search_users(user_id, key, search_by) | ||
if user_id.present? && (user = User.find_by(id: user_id)) | if user_id.present? && (user = User.find_by(id: user_id)) | ||
# If a valid user_id is provided, return the user with that specific user_id | # If a valid user_id is provided, return the user with that specific user_id | ||
return [user] | return [user] | ||
else | else | ||
# If user_id is empty or invalid, perform the search based on | # If user_id is empty or invalid, perform the search based on key and search_by parameters | ||
# Validate search_by to avoid SQL injection | # Validate search_by to avoid SQL injection | ||
Line 184: | Line 164: | ||
if search_by.present? | if search_by.present? | ||
# Use search_by directly in the where clause | # Use search_by directly in the where clause | ||
users = User.joins(:role).where("#{search_by} LIKE ?", "%#{ | users = User.joins(:role).where("#{search_by} LIKE ?", "%#{key}%").order(:name) if search_by == 'role' | ||
users ||= User.where("#{search_by} LIKE ?", "%#{ | users ||= User.where("#{search_by} LIKE ?", "%#{key}%").order(:name) | ||
return users | return users | ||
else | else | ||
Line 195: | Line 175: | ||
</source> | </source> | ||
In the login method of authentication controller we were getting NIL error. This was because the user did not have role and institution attributes. We updated the method to allow NIL values for these attributes. | |||
<source lang="ruby"> | <source lang="ruby"> | ||
Line 237: | Line 217: | ||
def search_users | def search_users | ||
user_id = params[:user_id] | user_id = params[:user_id] | ||
key = params[:key] | |||
search_by = params[:search_by] | search_by = params[:search_by] | ||
result = User.search_users(user_id, | result = User.search_users(user_id, key, search_by) | ||
if result.present? | if result.present? | ||
Line 253: | Line 233: | ||
This method facilitates dynamic user searches, allowing users to query the system based on different parameters. Users can search by `user_id`, and if it's empty or invalid, the search extends to attributes such as `name`, `full_name`, `email`, and `role`. The search results are ordered by the user's name. | This method facilitates dynamic user searches, allowing users to query the system based on different parameters. Users can search by `user_id`, and if it's empty or invalid, the search extends to attributes such as `name`, `full_name`, `email`, and `role`. The search results are ordered by the user's name. | ||
=== | === find by userid method=== | ||
Method for displaying the list of users. It supports seaching user by email. If email is not present the method searches for name. | |||
def self. | def self.find_by_userid(userid) | ||
user = User.find_by(email: | user = User.find_by(email: userid) | ||
if user.nil? | if user.nil? | ||
items = | items = userid.split('@') | ||
short_name = items[0] | short_name = items[0] | ||
user_list = User.where('name = ?', short_name) | user_list = User.where('name = ?', short_name) | ||
Line 276: | Line 247: | ||
end | end | ||
=== list Method === | === list and paginate_list Method === | ||
Method for | Method for filtering the users list with proper search and pagination. | ||
This list method is used to fetch the users and display them on certain criterias which are as follows: | |||
The search_by parameter accepts 'username', 'fullname' or 'email' as values and fetches the users based on this field. If no value for search_by is passed, all the users are displayed. | |||
The 'letter' parameter indicates the value used to match the users based on the field obtained via the search_by parameter mentioned above. | |||
In the paginate_list method, 'per_page' parameter indicates the number of users required to be displayed for each page. | |||
Three options are available for this parameter, 1, 2 and 3 mapped to 25, 50 and 100 users per page respectively. | |||
This default value for this parameter is 3, so if no value is passed for this parameter 100 users will be displayed. | |||
If a value more than 3 is passed, all the users will be displayed. | |||
def list | def list | ||
# code here | # code here | ||
Line 369: | Line 336: | ||
* '''user_id (optional)''': The ID of the requesting user. If provided, it is used to check if the user is a Super Administrator. | * '''user_id (optional)''': The ID of the requesting user. If provided, it is used to check if the user is a Super Administrator. | ||
* ''' | * '''key''': The search term. This is used to perform a LIKE query on the specified field. | ||
* '''search_by''': The field to search by. This can be 'name', 'email', 'full_name', 'id', or 'role'. | * '''search_by''': The field to search by. This can be 'name', 'email', 'full_name', 'id', or 'role'. | ||
Line 388: | Line 355: | ||
<pre> | <pre> | ||
GET /api/v1/users/search_users?user_id=1& | GET /api/v1/users/search_users?user_id=1&key=r&search_by=role | ||
</pre> | </pre> | ||
Line 461: | Line 428: | ||
</pre> | </pre> | ||
==== Postman Implementation ==== | ==== Postman Implementation ==== | ||
[[File:Postman1.jpg|800px]] | [[File:Postman1.jpg|800px]] | ||
Line 524: | Line 492: | ||
==== Postman Implementation ==== | ==== Postman Implementation ==== | ||
[[File:List_api.png|800px]] | [[File:List_api.png|800px]] | ||
== Test RSpec == | == Test RSpec == |
Latest revision as of 20:12, 9 December 2023
Description of Project
The project aims at reimplementing user controller.rb, user.rb and it's associated child classes. The project reimplementing functionalities specific to the above classes and write extensive rspec tests for the same.
Problem Statement
Background: Background: The User model is a key component of the Expertiza application, handling user data and authentication/authorization features. It is linked to other models such as Participant, TeamsUser, and Invitation, allowing for associations and a personalized user experience.
Reimplementation (What needs to be done): To set up the project, follow these instructions.
- Reimplement the search_users, find_user methods in user.rb
- Reimplement the list, paginate_list functionality in users_controller.rb
- Write thorough RSpec tests for the newly implemented functionalities
Objectives
- Reimplement methods pertaining to controller.rb, user.rb and it's associated child classes. More specifically reimplement search_users, find_user methods in user.rb.
- Reimplement the list, paginate_list functionality in users_controller.rb.
- Ensure proper naming of the methods, variables.
- Incorporate suggestions from project3.
- Ensure the PR checks are successfull and all test cases are passing.
- Compose comprehensive RSpec tests for the changes done to ensure the robustness and reliability of the entire system.
Development Strategy
We have started the development activity using TDD approach. We start by creating test cases for the functionality in hand. Since it is reimplementation, the existing code and functionality makes it much easier to select comprehensive test cases. This is followed by writing clean and simple code to pass the test cases. We are also incorporating comments we received as part of project 3. We identified few more places where naming could be better and we will be incorporating the suggested changes in the reimplementation project.
Revised User.rb:
- search_users Method:
- The 'search_users' method will be reimplemented to accept parameters such as 'role', 'user_id', 'letter', and 'search_by'.
- It will construct a SQL query based on the provided parameters to filter users.
- The method will return a list of users that match the search criteria.
- find_user Method:
- The 'find_user' method will be reimplemented to locate a user based on the provided login.
- It will first try to find the user by email. If not found, it will attempt to find the user by name.
- The method will return the found user or 'nil' if no matching user is found.
Revised UsersController.rb:
- list Action:
- The 'list' action will be reimplemented to handle listing of users.
- It will retrieve a list of users based on certain criteria, such as name, full name or email.
- paginate_list Action:
- The 'paginate_list' action will be reimplemented to handle paginated listing of users.
- It will retrieve a paginated list of users based on certain criteria, making it easier to display users in chunks.
RSpec Tests:
- User.rb Tests:
- RSpec tests for the 'search_users' method will ensure that the method correctly filters users based on the provided parameters.
- Tests for the 'find_user' method will validate that it successfully locates users by email or name.
- UsersController.rb Tests:
- Tests for the 'list' and 'paginate_list' action will check that it correctly paginates the list of users.
ToDo Status:
# | Task | Status | Notes |
---|---|---|---|
1 | Reimplement search_users method in User.rb
|
Done! | This method will be updated to accept parameters such as `role`, `user_id`, `letter`, and `search_by`. |
2 | Reimplement find_user method in User.rb
|
Done | This method will be updated to locate a user based on the provided login. |
3 | Reimplement list action in UsersController.rb
|
Done | This action will be updated to handle listing of users. |
4 | Reimplement paginate_list action in UsersController.rb
|
Done | This action will be updated to handle paginated listing of users. |
5 | Write RSpec tests for User.rb | Done | New tests will be written for the `search_users` and `find_user` methods. |
6 | Write RSpec tests for UsersController.rb | Done | New tests will be written for the `role` actions. |
Test Plan
Sr No | Test Description |
---|---|
1 | seacrh_users method in User.rb |
1.1 | Scenario 1: Test user search by name |
1.2 | Scenario 2: Test user search by email |
1.3 | Scenario 3: Test user search by fullname |
2 | find_user method in User.rb |
2.1 | Scenario 1: Test locate user by name |
2.2 | Scenario 2: Test locate user by email |
3 | list and paginate_list method in user_controller.rb |
3.1 | Scenario 1: checks that list and paginate_list does not fail with controller |
3.2 | Scenario 2: checks that list and paginate_list does not fail with post |
Implementation
Create users Using rails Console
Configure Compose as a remote interpreter
Connect MySQL DB and Application
Ruby syntax for creating a new user in a Rails application using the User model.
User.create!( name: 'newuser', # lowercase name email: 'new_user@example.com', password: 'password123', full_name: 'New User', role: Role.find_by(name: 'Super Administrator') )
Code
The search_users method accepts three parameters: user_id, key, and search_by. If a valid user_id is provided, the method returns an array containing the user with that specific user_id. In cases where user_id is empty or invalid, the method performs a search based on the provided key and search_by parameters. To prevent SQL injection, the method validates search_by against a predefined set of acceptable fields, including 'name', 'full_name', 'email', and 'role'. The search is then conducted using a LIKE query on the specified field, ordering the results by the user's name.
This flexible method accommodates various search scenarios, allowing users to query the system based on different criteria, enhancing the overall user experience.
def self.search_users(user_id, key, search_by)
if user_id.present? && (user = User.find_by(id: user_id))
# If a valid user_id is provided, return the user with that specific user_id
return [user]
else
# If user_id is empty or invalid, perform the search based on key and search_by parameters
# Validate search_by to avoid SQL injection
valid_search_fields = %w[name full_name email role]
search_by = valid_search_fields.include?(search_by) ? search_by : nil
# Perform the LIKE query on the specified field (name, full_name, email, role) and order by name
if search_by.present?
# Use search_by directly in the where clause
users = User.joins(:role).where("#{search_by} LIKE ?", "%#{key}%").order(:name) if search_by == 'role'
users ||= User.where("#{search_by} LIKE ?", "%#{key}%").order(:name)
return users
else
# If search_by is not recognized, return an empty result
return []
end
end
end
In the login method of authentication controller we were getting NIL error. This was because the user did not have role and institution attributes. We updated the method to allow NIL values for these attributes.
def login
user = User.find_by(name: params[:user_name]) || User.find_by(email: params[:user_name])
if user&.authenticate(params[:password])
payload = {
id: user.id,
name: user.name,
full_name: user.full_name,
role: user.role&.name, # Use safe navigation operator (&.) to avoid nil error
institution_id: user.institution&.id # Use safe navigation operator (&.) to avoid nil error
}
token = JsonWebToken.encode(payload, 24.hours.from_now)
render json: { token: token }, status: :ok # Include the actual token value in the response
else
render json: { error: 'Invalid username/password combination' }, status: :unauthorized
end
end
search_users Method
This method is designed to handle user search functionality in a web application. It retrieves parameters from the request to identify the current user, search criteria, and search type. It then calls the `search_users` method from the `User` model and renders the result accordingly.
Users can search by `user_id`, and if it's empty or invalid, the search extends to attributes such as `name`, `full_name`, `email`, and `role`. The search results are ordered by the user's name.
Attributes of user that can be searched by
- name: The name of the user.
- full_name: The full name of the user, providing a comprehensive representation.
- email: The unique email address associated with each user, ensuring distinct identification.
- role: A relationship with the Role model, defining the user's role and access privileges.
Result Handling
- If the result is a collection of users (`ActiveRecord::Relation`), it renders them as JSON.
def search_users user_id = params[:user_id] key = params[:key] search_by = params[:search_by]
result = User.search_users(user_id, key, search_by)
if result.present? # If the result is not empty, render the users as JSON render json: result else # If the result is empty, render a message as JSON with a not found status render json: { error: 'User not found or no matching results' }, status: :not_found end end
This method facilitates dynamic user searches, allowing users to query the system based on different parameters. Users can search by `user_id`, and if it's empty or invalid, the search extends to attributes such as `name`, `full_name`, `email`, and `role`. The search results are ordered by the user's name.
find by userid method
Method for displaying the list of users. It supports seaching user by email. If email is not present the method searches for name.
def self.find_by_userid(userid) user = User.find_by(email: userid) if user.nil? items = userid.split('@') short_name = items[0] user_list = User.where('name = ?', short_name) user = user_list.first if user_list.any? && user_list.length == 1 end user end
list and paginate_list Method
Method for filtering the users list with proper search and pagination.
This list method is used to fetch the users and display them on certain criterias which are as follows: The search_by parameter accepts 'username', 'fullname' or 'email' as values and fetches the users based on this field. If no value for search_by is passed, all the users are displayed. The 'letter' parameter indicates the value used to match the users based on the field obtained via the search_by parameter mentioned above.
In the paginate_list method, 'per_page' parameter indicates the number of users required to be displayed for each page. Three options are available for this parameter, 1, 2 and 3 mapped to 25, 50 and 100 users per page respectively. This default value for this parameter is 3, so if no value is passed for this parameter 100 users will be displayed. If a value more than 3 is passed, all the users will be displayed.
def list # code here letter = params[:letter] search_by = params[:search_by] # If search parameters present if letter.present? && search_by.present? case search_by.to_i when 1 # Search by username @paginated_users = paginate_list&.where('name LIKE ?', "%#{letter}%") when 2 # Search by fullname @paginated_users = paginate_list&.where('fullname LIKE ?', "%#{letter}%") when 3 # Search by email @paginated_users = paginate_list&.where('email LIKE ?', "%#{letter}%") else @paginated_users = paginate_list end else # Display all users if no search parameters present @paginated_users = paginate_list if @paginated_users puts("Not empty" + @paginated_users.to_s) else puts("Empty") end end render json: @paginated_users end
def paginate_list paginate_options = { '1' => 25, '2' => 50, '3' => 100 } # If the above hash does not have a value for the key, # it means that we need to show all the users on the page # # Just a point to remember, when we use pagination, the # 'users' variable should be an object, not an array # The type of condition for the search depends on what the user has selected from the search_by dropdown @search_by = params[:search_by] @per_page = params[:per_page] || 3 # search for corresponding users # users = User.search_users(role, user_id, letter, @search_by) # paginate users = if paginate_options[@per_page.to_s].nil? # displaying all - no pagination User.all else # some pagination is active - use the per_page User.paginate(page: params[:page], per_page: paginate_options[@per_page.to_s]) end # users = User.all users end
API Documentation
Swagger API
The image shows that we used Swagger to design and document our API application. Then, we exported the API data in JSON format to use Postman for development and testing. Postman is a tool that lets us send requests, check responses, write tests, and automate workflows for our API.
Postman Collection
Postman is an all-encompassing tool that enables us to send requests, validate responses, construct tests, and automate workflows for our Application Programming Interface (API). We have imported the Swagger API and created a Postman collection; this helps us to share the progress in real-time, facilitating online modifications because it is a SaaS application. In addition, we have put together a team workspace, as shown in the attached image. This arrangement fosters collaborative work and ensures the efficiency and effectiveness of our API operations.
Endpoint: Search Users
Description
The endpoint search by Users can search by `user_id`, and if it's empty or invalid, the search extends to attributes such as `name`, `full_name`, `email`, and `role`. The search results are ordered by the user's name.
Request
Method: GET
URL: /api/v1/users/search_users
Parameters:
- user_id (optional): The ID of the requesting user. If provided, it is used to check if the user is a Super Administrator.
- key: The search term. This is used to perform a LIKE query on the specified field.
- search_by: The field to search by. This can be 'name', 'email', 'full_name', 'id', or 'role'.
Swagger Endpoint
Response
Status Code: 200 OK
Body: A list of users that match the search term in the specified field.
Example
Request:
GET /api/v1/users/search_users?user_id=1&key=r&search_by=role
Response:
[ { "id": 1, "name": "root", "full_name": "New Super Administrator", "email": "root@example.com", "email_on_review": false, "email_on_submission": false, "email_on_review_of_review": false, "role": { "id": 1, "name": "Super Administrator" }, "parent": { "id": null, "name": null }, "institution": { "id": null, "name": null } }, { "id": 2, "name": "admin", "full_name": "Administrator", "email": "admin@example.com", "email_on_review": true, "email_on_submission": true, "email_on_review_of_review": true, "role": { "id": 2, "name": "Administrator" }, "parent": { "id": 1, "name": "root" }, "institution": { "id": 1, "name": "Institution 1" } }, { "id": 3, "name": "user", "full_name": "Regular User", "email": "user@example.com", "email_on_review": false, "email_on_submission": false, "email_on_review_of_review": false, "role": { "id": 3, "name": "Instructor" }, "parent": { "id": 2, "name": "admin" }, "institution": { "id": 2, "name": "Institution 2" } } ]
Postman Implementation
Request
Method: GET
URL: /api/v1/users/list
Parameters:
- search_by (optional): The field to search by. This can be 'name', 'email', 'full_name', 'id', or 'role'.
- letter (optional): The field to indicate the starting letter of the user's 'name', 'email', or 'full_name'.
- per_page (optional): The field to indicate how many users to be displayed per page.
Response
Status Code: 200 OK
Body: A list of users that match the search term in the specified field.
Example
Request:
GET api/v1/users/list?letter=n&search_by=1&per_page=3
Response:
[ { "id": 1, "name": "newuser", "full_name": "New User", "email": "new_user@example.com", "email_on_review": false, "email_on_submission": false, "email_on_review_of_review": false, "role": { "id": 1, "name": "Super Administrator" }, "parent": { "id": null, "name": null }, "institution": { "id": null, "name": null } } ]
Swagger Endpoint
Postman Implementation
Test RSpec
user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
describe '.find_by_login' do context 'when login is an email' do let!(:user) { create(:user, name: 'testname', email: 'test@test.com') } it 'returns the user with the matching email' do result = User.find_by_login('test@test.com') expect(result).to eq(user) end
it 'returns nil when user with email doesnt exist' do result = User.find_by_login('test@unknown.com') expect(result).to eq(nil) end end
context 'when login is not an email' do let!(:user) { create(:user, name: 'testname', email: 'test@test.com') } let!(:user2) { build(:user, name: 'testname', email: 'test@test2.com') } it 'returns the user with the matching name' do result = User.find_by_login('testname') expect(result).to eq(user) end it 'return first user with the matching name' do user2.save result = User.find_by_login('testname') expect(result).to eq(user) end it 'return nil when no user with matching name' do result = User.find_by_login('unknown') expect(result).to eq(nil) end end end
describe '.search_users' do # Creating dummy objects for the test with the help of let statement let(:role) { Role.create(name: 'Instructor', parent_id: nil, id: 2, default_page_id: nil) } let(:instructor) do Instructor.create(id: 1234, name: 'testinstructor', email: 'test@test.com', full_name: 'Test Instructor', password: '123456', role_id: 2) end
context 'when searching by name' do it 'returns users with matching names' do # Test scenario 1 search_result = User.search_users(nil, 'testins', 'name') expect(search_result).to include(instructor) # Test scenario 2 search_result = User.search_users(nil, 'unknown', 'name') expect(search_result).to be_empty end end
context 'when searching by fullname' do it 'returns users with matching fullnames' do # Test scenario 1 search_result = User.search_users(nil, 'Test', 'full_name') expect(search_result).to include(instructor) # Test scenario 2 search_result = User.search_users(nil, 'UnknownName', 'full_name') expect(search_result).to be_empty end end
context 'when searching by email' do it 'returns users with matching emails' do # Test scenario 1 search_result = User.search_users(nil, 'test@test.com', 'email') expect(search_result).to include(instructor) # Test scenario 2 search_result = User.search_users(nil, 'unknown@test.com', 'email') expect(search_result).to be_empty end end
context 'when searching by default' do it 'returns users with names starting with the specified id' do # Test scenario 1 search_result = User.search_users(instructor.id, nil, nil) expect(search_result.map(&:id)).to include(instructor.id) # Test scenario 2 search_result = User.search_users(9999, nil, nil) # Use an invalid user_id expect(search_result).to be_empty end end context 'when searching by role' do it 'returns users with matching roles' do # Test scenario 1 search_result = User.search_users(nil, 'admin', 'role') expect(search_result.map(&:id)).to include(instructor.role_id) # Test scenario 2 search_result = User.search_users(nil, 'unknown', 'role') expect(search_result).to be_empty end end end
end
Test Results
Team
Mentor
- Devashish Vachhani
Members
- Doddaguni, Sachin R
- Mahesh, Amogh
- Villar, Sergio Vargas