Untitled

 avatar
unknown
plain_text
20 days ago
19 kB
4
Indexable
import io.cucumber.java.en.Then;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Step definitions for testing the NNS Recommendations Personalized API.
 */
public class NnsRecommendationsStepDefinitions {

    // Required fields in the response
    private static final String[] REQUIRED_RECOMMENDATIONS_FIELDS = {
        "type", "uiHint", "vodOutOfWindow", "name", "twcTvNetworkDisplayMode", 
        "results", "num_categories", "total_results", "start_index", 
        "num_results", "max_results", "dsQueryId", "curationType", "dynamicUris"
    };

    // Required fields in each result item (common fields for both event and episode_list)
    private static final String[] REQUIRED_RESULT_FIELDS = {
        "type", "alphaSortOn", "availableOutOfHome", "details", "title", "uri", "skeletonShelf"
    };

    // Required fields specific to event type
    private static final String[] REQUIRED_EVENT_FIELDS = {
        "tmsProgramIds", "providerAssetIds", "image_uri", "network"
    };

    // Required fields specific to episode_list type
    private static final String[] REQUIRED_EPISODE_LIST_FIELDS = {
        "tmsSeriesId", "tmsSeriesIdStr", "tmsGuideServiceIds", "image_uri", "network"
    };

    // Required fields in details object for event
    private static final String[] REQUIRED_EVENT_DETAILS_FIELDS = {
        "genres", "allRatings", "allVPPs", "allIpVPPs", "entitled", 
        "tvodEntitled", "linearEntitledIp", "linearEntitledQam"
    };

    // Required fields in details object for episode_list
    private static final String[] REQUIRED_EPISODE_LIST_DETAILS_FIELDS = {
        "num_assets", "totalEpisodes", "latest_episode", "allRatings", "allVPPs", "allIpVPPs"
    };

    // Required fields in network object
    private static final String[] REQUIRED_NETWORK_FIELDS = {
        "callsign", "image_uri", "name", "product_provider"
    };

    /**
     * Tests the NNS Recommendations Personalized API with the given parameters and compares with Search API.
     * 
     * @param division The division parameter
     * @param vodId The vodId parameter
     * @param lineup The lineup parameter
     * @param useridhash The useridhash parameter
     */
    @Then("The NNS recommendations personalized call with division {string}, vodId {string}, lineup {string}, and useridhash {string} should return expected data structure")
    public void request_and_verify_nns_recommendations_personalized(String division, String vodId, String lineup, String useridhash) {
        // Create the request parameters for NNS
        RequestParams params = new RequestParams();
        params.add("division", division);
        params.add("vodId", vodId);
        params.add("lineup", lineup);
        params.add("path", "1757001972");
        params.add("useridhash", useridhash);
        params.add("recommendationKey", "HNAV_VOD_Free_");
        params.add("profile", "{client_nns_profile}");
        params.add("cacheID", "280");
        params.add("application", "VOD_PORTAL");
        params.add("profileConfigurationEnablePersonalizedRecommendations", "true");
        params.add("profileConfigurationHttpCachingStrategy", "MAX_AGE");
        params.add("profileConfigurationIncludeNielsenReporting", "true");
        params.add("profileConfigurationSearchUseBkm", "true");
        params.add("profileConfigurationTwctvClientUseActionGroupsWholeApp", "true");
        params.add("tvodRent", "true");
        params.add("tvodWatch", "true");
        params.add("cdvrEnabled", "true");
        params.add("deviceLocation", "In_Home");
        params.add("watchOnDemand", "true");
        params.add("hideOnDemand", "false");
        params.add("watchLive", "true");
        
        // Add cookie header
        Map<String, String> headers = new HashMap<>();
        headers.put("Cookie", "dla_marker=9febad42-bf50-4142-8ce1-812361e31a4b");
        
        // Make the NNS API call
        ServiceApiResponse nnsResponse = restNNS().apiRecommendationsPersonalized(params, headers).get();
        
        // Verify the response status
        assertTrue("NNS recommendations personalized API call failed with status: " + nnsResponse.status() + 
                   " and TXID: " + nnsResponse.txId(), nnsResponse.isSuccess());
        
        // Parse the JSON response
        JSON nnsJson = nnsResponse.json();
        
        // Log response for debugging
        Logger.info("NNS API Response: " + nnsJson.toString());
        
        // Validate the required fields in the response
        validateRequiredFields(nnsJson, REQUIRED_RECOMMENDATIONS_FIELDS, "Root object");
        
        // Validate the results array
        validateResultsArray(nnsJson.get("results"));
        
        // Additional validation
        assertEquals("Expected name to be 'Personalized'", "Personalized", nnsJson.getString("name"));
        assertEquals("Expected curationType to be 'personalized'", "personalized", nnsJson.getString("curationType"));
        assertTrue("Expected at least one dynamic URI", nnsJson.getArraySize("dynamicUris") > 0);
        
        // Extract tmsProgramIds from NNS response for comparison with Search API
        List<String> tmsProgramIds = extractTmsProgramIds(nnsJson.get("results"));
        
        // If we have tmsProgramIds, make the search API call for comparison
        if (!tmsProgramIds.isEmpty()) {
            compareWithSearchApi(tmsProgramIds, division, vodId, lineup);
        }
    }
    
    /**
     * Validates that the given JSON object contains all required fields.
     */
    private void validateRequiredFields(JSON json, String[] requiredFields, String objectName) {
        for (String field : requiredFields) {
            assertTrue(objectName + " missing required field: " + field, json.hasField(field));
        }
    }
    
    /**
     * Validates the results array in the response.
     */
    private void validateResultsArray(JSON results) {
        assertTrue("Results should be an array", results.isArray());
        assertTrue("Results array should not be empty", results.size() > 0);
        
        boolean foundEventType = false;
        boolean foundEpisodeListType = false;
        
        // Validate each result item
        for (int i = 0; i < results.size(); i++) {
            JSON result = results.get(i);
            
            // Validate common fields for all result types
            validateRequiredFields(result, REQUIRED_RESULT_FIELDS, "Result item " + i);
            
            // Validate type-specific fields and track if we've found each type
            String type = result.getString("type");
            if ("event".equals(type)) {
                foundEventType = true;
                validateEventType(result, i);
            } else if ("episode_list".equals(type)) {
                foundEpisodeListType = true;
                validateEpisodeListType(result, i);
            }
        }
        
        // Ensure we've found at least one of each type for comprehensive validation
        assertTrue("No 'event' type found in results", foundEventType);
        assertTrue("No 'episode_list' type found in results", foundEpisodeListType);
    }
    
    /**
     * Validates an event type result.
     */
    private void validateEventType(JSON event, int index) {
        // Validate event-specific fields
        validateRequiredFields(event, REQUIRED_EVENT_FIELDS, "Event " + index);
        
        // Validate details object
        JSON details = event.get("details");
        validateRequiredFields(details, REQUIRED_EVENT_DETAILS_FIELDS, "Event " + index + " details");
        
        // Validate genres array
        JSON genres = details.get("genres");
        assertTrue("Genres should be an array", genres.isArray());
        if (genres.size() > 0) {
            for (int i = 0; i < genres.size(); i++) {
                assertTrue("Genre " + i + " should have a name", genres.get(i).hasField("name"));
            }
        }
        
        // Validate arrays
        validateArrayField(details, "allRatings");
        validateArrayField(details, "allVPPs");
        validateArrayField(details, "allIpVPPs");
        validateArrayField(event, "tmsProgramIds");
        validateArrayField(event, "providerAssetIds");
        validateArrayField(event, "tmsGuideServiceIds", true); // Optional field
        validateArrayField(event, "ipTmsGuideServiceIds", true); // Optional field
        
        // Validate network
        validateNetwork(event.get("network"));
        
        // Validate streamList if present
        if (event.hasField("streamList")) {
            validateStreamList(event.get("streamList"));
        }
    }
    
    /**
     * Validates an episode_list type result.
     */
    private void validateEpisodeListType(JSON episodeList, int index) {
        // Validate episode_list-specific fields
        validateRequiredFields(episodeList, REQUIRED_EPISODE_LIST_FIELDS, "Episode list " + index);
        
        // Validate details object
        JSON details = episodeList.get("details");
        validateRequiredFields(details, REQUIRED_EPISODE_LIST_DETAILS_FIELDS, "Episode list " + index + " details");
        
        // Validate latest_episode
        validateLatestEpisode(details.get("latest_episode"));
        
        // Validate arrays
        validateArrayField(details, "allRatings");
        validateArrayField(details, "allVPPs");
        validateArrayField(details, "allIpVPPs");
        validateArrayField(episodeList, "tmsGuideServiceIds");
        validateArrayField(episodeList, "ipTmsGuideServiceIds");
        
        // Validate network
        validateNetwork(episodeList.get("network"));
    }
    
    /**
     * Validates the latest_episode object in an episode_list.
     */
    private void validateLatestEpisode(JSON latestEpisode) {
        assertTrue("Latest episode should have type field", latestEpisode.hasField("type"));
        assertTrue("Latest episode should have details field", latestEpisode.hasField("details"));
        assertTrue("Latest episode should have title field", latestEpisode.hasField("title"));
        
        // Validate latest episode details
        JSON details = latestEpisode.get("details");
        assertTrue("Latest episode details should have genres field", details.hasField("genres"));
        
        // Validate genres array
        JSON genres = details.get("genres");
        assertTrue("Genres should be an array", genres.isArray());
        if (genres.size() > 0) {
            for (int i = 0; i < genres.size(); i++) {
                assertTrue("Genre " + i + " should have a name", genres.get(i).hasField("name"));
            }
        }
        
        // Validate network if present
        if (latestEpisode.hasField("network")) {
            validateNetwork(latestEpisode.get("network"));
        }
        
        // Validate streamList if present
        if (latestEpisode.hasField("streamList")) {
            validateStreamList(latestEpisode.get("streamList"));
        }
    }
    
    /**
     * Validates the network object.
     */
    private void validateNetwork(JSON network) {
        validateRequiredFields(network, REQUIRED_NETWORK_FIELDS, "Network");
        
        // Validate product_providers array if present
        if (network.hasField("product_providers")) {
            validateArrayField(network, "product_providers");
        }
    }
    
    /**
     * Validates the stream list array.
     */
    private void validateStreamList(JSON streamList) {
        assertTrue("Stream list should be an array", streamList.isArray());
        
        for (int i = 0; i < streamList.size(); i++) {
            JSON stream = streamList.get(i);
            
            // Validate required fields
            assertTrue("Stream " + i + " missing type field", stream.hasField("type"));
            
            // Validate streamProperties if present
            if (stream.hasField("streamProperties")) {
                JSON props = stream.get("streamProperties");
                assertTrue("Stream properties should have entitled field", props.hasField("entitled"));
                
                // Validate nielsenReporting if present
                if (props.hasField("nielsenReporting")) {
                    JSON nielsen = props.get("nielsenReporting");
                    validateArrayField(nielsen, "metrics");
                    validateArrayField(nielsen, "locations");
                }
            }
            
            // Validate network if present
            if (stream.hasField("network")) {
                validateNetwork(stream.get("network"));
            }
        }
    }
    
    /**
     * Validates that the given field is an array.
     */
    private void validateArrayField(JSON json, String fieldName) {
        validateArrayField(json, fieldName, false);
    }
    
    /**
     * Validates that the given field is an array.
     * 
     * @param json The JSON object containing the field
     * @param fieldName The name of the field to validate
     * @param optional Whether the field is optional
     */
    private void validateArrayField(JSON json, String fieldName, boolean optional) {
        if (json.hasField(fieldName)) {
            Object field = json.get(fieldName);
            assertTrue(fieldName + " is not an array", (field instanceof JSON) && ((JSON) field).isArray());
        } else if (!optional) {
            fail("Required array field " + fieldName + " is missing");
        }
    }
    
    /**
     * Extracts all tmsProgramIds from the results array.
     */
    private List<String> extractTmsProgramIds(JSON results) {
        List<String> tmsProgramIds = new ArrayList<>();
        
        for (int i = 0; i < results.size(); i++) {
            JSON result = results.get(i);
            String type = result.getString("type");
            
            if ("event".equals(type) && result.hasField("tmsProgramIds")) {
                JSON ids = result.get("tmsProgramIds");
                for (int j = 0; j < ids.size(); j++) {
                    tmsProgramIds.add(ids.getString(j));
                }
            } else if ("episode_list".equals(type) && result.hasField("details")) {
                JSON details = result.get("details");
                if (details.hasField("latest_episode")) {
                    JSON latestEpisode = details.get("latest_episode");
                    if (latestEpisode.hasField("tmsProgramIds")) {
                        JSON ids = latestEpisode.get("tmsProgramIds");
                        for (int j = 0; j < ids.size(); j++) {
                            tmsProgramIds.add(ids.getString(j));
                        }
                    }
                }
            }
        }
        
        return tmsProgramIds;
    }
    
    /**
     * Compares the NNS response with the Search API response.
     */
    private void compareWithSearchApi(List<String> tmsProgramIds, String division, String vodId, String lineup) {
        // Build search API request
        RequestParams searchParams = new RequestParams();
        searchParams.add("dynListKey", "HNAV_VOD_Free_");
        searchParams.add("callerAppName", "TWCTV");
        searchParams.add("offset", "0");
        searchParams.add("maxResults", "15");
        searchParams.add("direction", "FORWARD");
        searchParams.add("sortType", "PERSONALIZED");
        searchParams.add("programAttribute", "HighDefinition,StdDefinition");
        searchParams.add("alAdultCont", "false");
        searchParams.add("contType", "SERIES,MOVIE,PROGRAM");
        searchParams.add("linTRange", "NOW_TO_13_DAYS_MIDNIGHT");
        searchParams.add("exclSeriesEpisodes", "false");
        searchParams.add("vodLicWind", "IN_WINDOW");
        searchParams.add("filterPPV", "true");
        searchParams.add("filterOutSVOD", "false");
        searchParams.add("sppEnabled", "false");
        searchParams.add("incLetInd", "false");
        searchParams.add("linTRangeEndMs", "0");
        searchParams.add("linTRangeStartMs", "0");
        searchParams.add("billingAccountId", "8347100040106596");
        searchParams.add("billingDivision", "LNK.8347");
        searchParams.add("includeUnmapped", "true");
        searchParams.add("locDiv", division);
        searchParams.add("locLup", lineup);
        searchParams.add("contSourLin", "IP");
        searchParams.add("contSourVod", "IP");
        searchParams.add("contSourTVod", "BOTH_AND");
        searchParams.add("vodDiv", division);
        searchParams.add("includeSchedule", "false");
        searchParams.add("resultFieldSet", "IDS");
        searchParams.add("groupingField", "GROUP_ID");
        
        // Make the Search API call
        ServiceApiResponse searchResponse = restSearch().apiAssetSearchDynamicList(searchParams).get();
        
        // Verify the response status
        assertTrue("Search API call failed with status: " + searchResponse.status() + 
                   " and TXID: " + searchResponse.txId(), searchResponse.isSuccess());
        
        // Parse the JSON response
        JSON searchJson = searchResponse.json();
        
        // Log response for debugging
        Logger.info("Search API Response: " + searchJson.toString());
        
        // Extract tmsIds from search response
        List<String> searchTmsIds = extractSearchTmsIds(searchJson);
        
        // Compare TMS IDs from both responses
        Logger.info("Comparing TMS IDs between NNS and Search APIs");
        Logger.info("NNS TMS IDs: " + tmsProgramIds);
        Logger.info("Search TMS IDs: " + searchTmsIds);
        
        // Validate that at least some of the IDs match (not all will match exactly)
        boolean foundMatch = false;
        for (String nnsId : tmsProgramIds) {
            if (searchTmsIds.contains(nnsId)) {
                foundMatch = true;
                break;
            }
        }
        
        assertTrue("No matching TMS IDs found between NNS and Search APIs", foundMatch);
    }
    
    /**
     * Extracts tmsIds from the Search API response.
     */
    private List<String> extractSearchTmsIds(JSON searchJson) {
        List<String> tmsIds = new ArrayList<>();
        
        if (searchJson.hasField("assets")) {
            JSON assets = searchJson.get("assets");
            for (int i = 0; i < assets.size(); i++) {
                JSON asset = assets.get(i);
                if (asset.hasField("tmsId")) {
                    tmsIds.add(asset.getString("tmsId"));
                }
            }
        }
        
        return tmsIds;
    }
}
Editor is loading...
Leave a Comment