Skip to content

Commit

Permalink
implemented View Customer Details in Admin UI
Browse files Browse the repository at this point in the history
changed customers.feature, web_steps.py, index.html and rest_api.js
  • Loading branch information
kutdkutf43 committed Apr 16, 2024
1 parent db03c7d commit 8298f0d
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 36 deletions.
9 changes: 8 additions & 1 deletion features/customers.feature
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,11 @@ Scenario: List all Customers
And I should see "kaite5" in the results
And I should see "gigi44" in the results
And I should see "lion15" in the results
And I should see "natedog" in the results
And I should see "natedog" in the results

@view_customer_details
Scenario: View details of a customer
When I visit the "Home Page"
And I press the "List" button
And I press the "View Details" button for the first customer
Then I should see all details for the customer in a modal
112 changes: 82 additions & 30 deletions features/steps/web_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,72 +30,81 @@
from selenium.webdriver.support.ui import Select, WebDriverWait
from selenium.webdriver.support import expected_conditions

ID_PREFIX = 'customer_'
ID_PREFIX = "customer_"


@when('I visit the "Home Page"')
def step_impl(context):
""" Make a call to the base URL """
"""Make a call to the base URL"""
context.driver.get(context.base_url)
# Uncomment next line to take a screenshot of the web page
# context.driver.save_screenshot('home_page.png')


@then('I should see "{message}" in the title')
def step_impl(context, message):
""" Check the document title for a message """
assert(message in context.driver.title)
"""Check the document title for a message"""
assert message in context.driver.title


@then('I should not see "{text_string}"')
def step_impl(context, text_string):
element = context.driver.find_element(By.TAG_NAME, 'body')
assert(text_string not in element.text)
element = context.driver.find_element(By.TAG_NAME, "body")
assert text_string not in element.text


@when('I set the "{element_name}" to "{text_string}"')
def step_impl(context, element_name, text_string):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = context.driver.find_element(By.ID, element_id)
element.clear()
element.send_keys(text_string)


@when('I select "{text}" in the "{element_name}" dropdown')
def step_impl(context, text, element_name):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = Select(context.driver.find_element(By.ID, element_id))
element.select_by_visible_text(text)


@then('I should see "{text}" in the "{element_name}" dropdown')
def step_impl(context, text, element_name):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = Select(context.driver.find_element(By.ID, element_id))
assert(element.first_selected_option.text == text)
assert element.first_selected_option.text == text


@then('the "{element_name}" field should be empty')
def step_impl(context, element_name):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = context.driver.find_element(By.ID, element_id)
assert(element.get_attribute('value') == u'')
assert element.get_attribute("value") == ""


##################################################################
# These two function simulate copy and paste
##################################################################
@when('I copy the "{element_name}" field')
def step_impl(context, element_name):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = WebDriverWait(context.driver, context.wait_seconds).until(
expected_conditions.presence_of_element_located((By.ID, element_id))
)
context.clipboard = element.get_attribute('value')
logging.info('Clipboard contains: %s', context.clipboard)
context.clipboard = element.get_attribute("value")
logging.info("Clipboard contains: %s", context.clipboard)


@when('I paste the "{element_name}" field')
def step_impl(context, element_name):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = WebDriverWait(context.driver, context.wait_seconds).until(
expected_conditions.presence_of_element_located((By.ID, element_id))
)
element.clear()
element.send_keys(context.clipboard)


##################################################################
# This code works because of the following naming convention:
# The buttons have an id in the html hat is the button text
Expand All @@ -104,35 +113,38 @@ def step_impl(context, element_name):
# to get the element id of any button
##################################################################


@when('I press the "{button}" button')
def step_impl(context, button):
button_id = button.lower() + '-btn'
button_id = button.lower() + "-btn"
context.driver.find_element(By.ID, button_id).click()


@then('I should see "{name}" in the results')
def step_impl(context, name):
found = WebDriverWait(context.driver, context.wait_seconds).until(
expected_conditions.text_to_be_present_in_element(
(By.ID, 'search_results'),
name
(By.ID, "search_results"), name
)
)
assert(found)
assert found


@then('I should not see "{name}" in the results')
def step_impl(context, name):
element = context.driver.find_element(By.ID, 'search_results')
assert(name not in element.text)
element = context.driver.find_element(By.ID, "search_results")
assert name not in element.text


@then('I should see the message "{message}"')
def step_impl(context, message):
found = WebDriverWait(context.driver, context.wait_seconds).until(
expected_conditions.text_to_be_present_in_element(
(By.ID, 'flash_message'),
message
(By.ID, "flash_message"), message
)
)
assert(found)
assert found


##################################################################
# This code works because of the following naming convention:
Expand All @@ -141,22 +153,62 @@ def step_impl(context, message):
# We can then lowercase the name and prefix with pet_ to get the id
##################################################################


@then('I should see "{text_string}" in the "{element_name}" field')
def step_impl(context, text_string, element_name):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
found = WebDriverWait(context.driver, context.wait_seconds).until(
expected_conditions.text_to_be_present_in_element_value(
(By.ID, element_id),
text_string
(By.ID, element_id), text_string
)
)
assert(found)
assert found


@when('I change "{element_name}" to "{text_string}"')
def step_impl(context, element_name, text_string):
element_id = ID_PREFIX + element_name.lower().replace(' ', '_')
element_id = ID_PREFIX + element_name.lower().replace(" ", "_")
element = WebDriverWait(context.driver, context.wait_seconds).until(
expected_conditions.presence_of_element_located((By.ID, element_id))
)
element.clear()
element.send_keys(text_string)


from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


@when('I press the "View Details" button for the first customer')
def step_impl(context):
button = WebDriverWait(context.driver, 10).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".view-details-btn"))
)
button.click()


@then("I should see all details for the customer in a modal")
def step_impl(context):
WebDriverWait(context.driver, 10).until(
EC.visibility_of_element_located((By.ID, "customerDetailsModal"))
)
modal = context.driver.find_element(By.ID, "customerDetailsModal")
assert modal.is_displayed(), "Modal is not displayed"
# Check for specific fields within the modal
details = [
"detail-username",
"detail-first-name",
"detail-last-name",
"detail-email",
]
for detail in details:
assert (
context.driver.find_element(By.ID, detail).text != ""
), f"{detail} is empty"


@when("I am on the customer list page")
def step_impl(context):
context.driver.get(context.base_url + "/path-to-customer-list")
# Assuming the list page is part of the main home page, modify as necessary
28 changes: 28 additions & 0 deletions service/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,31 @@ <h3>Create, Retrieve, Update, and Delete a Customer:</h3>

</body>
</html>

<!-- Detail View for a customer -->
<div id="customerDetailsModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Customer Details</h4>
</div>
<div class="modal-body" >

<p>ID: <span id="detail-id"></span></p>
<p>Username: <span id="detail-username"></span></p>
<p>First Name: <span id="detail-first-name"></span></p>
<p>Last Name: <span id="detail-last-name"></span></p>
<p>Gender: <span id="detail-gender"></span></p>
<p>Active: <span id="detail-active"></span></p>
<p>Address: <span id="detail-address"></span></p>
<p>Email: <span id="detail-email"></span></p>

</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

57 changes: 52 additions & 5 deletions service/static/js/rest_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,27 @@ $("#list-btn").click(function () {
table += '<th class="col-md-2">Active</th>'
table += '</tr></thead><tbody>'
let firstCustomer = "";
// for (let i = 0; i < res.length; i++) {
// let customer = res[i];
// table += `<tr id="row_${i}"><td>${customer.id}</td><td>${customer.username}</td><td>${customer.first_name}</td><td>${customer.last_name}</td><td>${customer.email}</td><td>${customer.active}</td></tr>`;
// if (i == 0) {
// firstCustomer = customer;
// }
// }

for (let i = 0; i < res.length; i++) {
let customer = res[i];
table += `<tr id="row_${i}"><td>${customer.id}</td><td>${customer.username}</td><td>${customer.first_name}</td><td>${customer.last_name}</td><td>${customer.email}</td><td>${customer.active}</td></tr>`;
if (i == 0) {
firstCustomer = customer;
}
table += `<tr id="row_${customer.id}" class="customer-row" data-customer-id="${customer.id}">
<td>${customer.id}</td>
<td>${customer.username}</td>
<td>${customer.first_name}</td>
<td>${customer.last_name}</td>
<td>${customer.email}</td>
<td>${customer.active}</td>
<td><button class="btn btn-info view-details-btn" data-customer-id="${customer.id}">View Details</button></td>
</tr>`;
}

table += '</tbody></table>';
$("#search_results").append(table);

Expand All @@ -128,4 +142,37 @@ $("#list-btn").click(function () {
flash_message(res.responseJSON.message)
});
});
})
})


// Event Listener for 'View Details' Button Clicks
$(document).on('click', '.view-details-btn', function() {
var customerId = $(this).data('customer-id');
fetchCustomerDetails(customerId);
});

// The function fetchCustomerDetails should send an AJAX request to your server to retrieve customer data and then display it in the modal
function fetchCustomerDetails(customerId) {
$.ajax({
type: "GET",
url: "/customers/" + customerId,
contentType: "application/json",
success: function(response) {
// Assuming 'response' is the customer data
$('#detail-id').text(response.id);
$('#detail-username').text(response.username);
$('#detail-first-name').text(response.first_name);
$('#detail-last-name').text(response.last_name);

$('#detail-gender').text(response.gender);
$('#detail-active').text(response.active ? 'True' : 'False');
$('#detail-address').text(response.address);
$('#detail-email').text(response.email);
// Show the modal
$('#customerDetailsModal').modal('show');
},
error: function(xhr) {
flash_message('Error: ' + xhr.responseJSON.message);
}
});
}

0 comments on commit 8298f0d

Please sign in to comment.