Skip to content

Commit

Permalink
update to version 1.1.0. fix dependencies. code refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
RokuRnD committed Jan 25, 2017
1 parent d15a372 commit 79452b4
Show file tree
Hide file tree
Showing 67 changed files with 5,160 additions and 0 deletions.
1,939 changes: 1,939 additions & 0 deletions UnitTestFramework.brs

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions samples/SimpleTestApp/dev/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1. Run import_unit_test_framework.bat or ./import_unit_test_framework.sh or
place the UnitTestFramework.brs file to the testFramework folder manually.
2. Sideload the app to the box.
3. To run the tests, issue the following ECP command:
curl -d '' 'http://{Roku Device IP Address}:8060/launch/dev?RunTests=true'

Documentation: https://github.com/rokudev/unit-testing-framework
1 change: 1 addition & 0 deletions samples/SimpleTestApp/dev/import_unit_test_framework.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
copy /Y /B ..\..\..\UnitTestFramework.brs source\testFramework\UnitTestFramework.brs
2 changes: 2 additions & 0 deletions samples/SimpleTestApp/dev/import_unit_test_framework.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
cat ../../../UnitTestFramework.brs > source/testFramework/UnitTestFramework.brs
30 changes: 30 additions & 0 deletions samples/SimpleTestApp/dev/manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#
# Copyright (c) 2017 Roku, Inc. All rights reserved.
# Roku Channel Manifest File
# Full spec at bit.ly/roku-manifest-file
#

## Channel Details
title=unit_test_fw_sample
major_version=1
minor_version=1
build_version=0

## Channel Assets
### Main Menu Icons / Channel Poster Artwork
#### Image sizes are FHD: 540x405px | HD: 290x218px | SD: 214x144px
mm_icon_focus_hd=pkg:/images/MainMenu_Icon_Center_HD.png
mm_icon_focus_sd=pkg:/images/MainMenu_Icon_Center_SD43.png

### Legacy Required Manifest Attributes
#### Image sizes are HD: 108x69px | SD: 248x140px
mm_icon_side_hd=pkg:/images/MainMenu_Icon_Side_HD.png
mm_icon_side_sd=pkg:/images/MainMenu_Icon_Side_SD43.png

### Splash Screen + Loading Screen Artwork
#### Image sizes are FHD: 1920x1080px | HD: 1280x720px | SD: 720x480px
splash_screen_fhd=pkg:/images/splash_fhd.jpg
splash_screen_hd=pkg:/images/splash_hd.jpg
splash_screen_sd=pkg:/images/splash_sd.jpg

ui_resolutions=hd
214 changes: 214 additions & 0 deletions samples/SimpleTestApp/dev/source/Utils.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
' ********** Copyright 2017 Roku Corp. All Rights Reserved. **********

'****************************************************************
'Common channel utility functions
'****************************************************************
'contains:
' - RSG help utilities
' - string utils functionality
' - parse functionality
'****************************************************************



'================================================================
' RSG help utilities
'================================================================



'*****************************************************************
' Copies all fields from associative array to content node.
' Generally used for transforming parsed conetent from feed
' to special node type that is used by other RSG nodes.
' @param contentList As Object - associative array
' @return As Object - valid ContentNode
'*****************************************************************
function Utils_ContentList2Node(contentList as Object) as Object
result = createObject("roSGNode","ContentNode")

for each itemAA in contentList
item = createObject("roSGNode", "ContentNode")
for each field in itemAA
if item.hasField(field)
item[field] = itemAA[field]
end if
end for
result.appendChild(item)
end for

return result
end function


'*****************************************************************
' Copies ContentNode to anouther ContentNode.
' Generally used for contentNode copying with some filtering.
' @param node As Object - node to copy
' @param nodeType as String - type of new node
' @param fieldsFilterAA as Object - roAA of fields to filter
' @return As Object - copied node
'*****************************************************************
Function Utils_CopyNodeContent(node as Object, nodeType = "ContentNode" as String, fieldsFilterAA = {} as Object)
item = createObject("roSGNode", nodeType)

if node = invalid then return item

existingFields = {}
newFields = {}

'AA of node read-only fields for filtering'
if fieldsFilterAA = invalid OR fieldsFilterAA.Count() = 0
fieldsFilterAA = {
focusedChild : "focusedChild"
change : "change"
}
end if

for each field in node.getFields()
if item.hasField(field) AND NOT fieldsFilterAA.doesExist(field)
existingFields[field] = node[field]
else
newFields[field] = node[field]
end if
end for

item.setFields(existingFields)
item.addFields(newFields)

return item
End Function

'*****************************************************************
' This will return the parent node that goes as parameter
' otherwise return m.top.
' Used for getting valid parent node of requested node.
' @param nodeName As String - node name
' @return As Object - valid parent Node
'*****************************************************************
function Utils_getParent(nodeName as String) as Object
node = m.top

while node <> invalid and lCase(node.subtype()) <> lCase(nodeName)
node = node.getParent()
end while

return node
end function

'*****************************************************************
' Add next panel to the Sliding Panel
' Simple wrapper function that helps configure and add node
' for RSG Sliding Panels (classes that allow you set up panels
' of content that slide on and off the display screen.)
' When the createNextPanlOnItemFocus field is true,
' the nextPanel field should be set to a Panel node to the next panel to
' add to the PanelSet in response to the createNextPanelIndex field being set.
' It must be set immediately in repsonse to createNextPanelIndex field being set.
' @param nextPanelName As Object - name of panel to add
' @param data As Object - data to set in new panel
' @param goBackCount As Object - back functionality
' @param isLeftOnly As Object - check is only left panel
'*****************************************************************
sub Utils_addNextPanel(nextPanelName as Object, data = {} as Object, goBackCount = 1 as Integer,isLeftOnly = invalid as object)
isSimplePanel = m.top.parentSubtype(m.top.subtype()) = "Panel"

if isSimplePanel and not m.top.hasField("nextPanel")
m.top.addField("nextPanel", "node", true)
end if

if type(nextPanelName) = "roString"
newPanel = createObject("roSGNode", nextPanelName)
if newPanel <> invalid
if isLeftOnly <> invalid and type(isLeftOnly) = "roBoolean"
newPanel.leftOnly = isLeftOnly
end if
m.top.nextPanel = newPanel
if newPanel.hasField("data")
newPanel.data = data
end if
m.top.nextPanel.goBackCount = goBackCount
if isSimplePanel
parentPanelSet = Utils_getParent("PanelSet")
parentPanelSet.appendChild(m.top.nextPanel)
m.top.setFocus(false)
m.top.nextPanel.setFocus(true)
end if
else
?"failed to create new panel"
end if
end if
end sub

'*****************************************************************
' Set necessary properties to overhang node
' Wrapper function that helps configurate properlyglobal Overhang node.
' The Overhang node provides a information bar that is displayed at the top of
' a screen in many Roku channels. The regions occupied by the overhang
' can be filled with either a solid color or a bitmap.
' @param title As String - title
' @param optionsAvaliable As Object - are options avaliable
' @param showOptions As Object - show avaliable options
'*****************************************************************
sub Utils_setOverhangData(title as String, optionsAvaliable = false as boolean, showOptions = optionsAvaliable as Boolean)
overhang = m.global.overhang
if overhang <> invalid
overhang.showOptions = showOptions
overhang.optionsAvailable = optionsAvaliable
overhang.title = title
end if
end sub


'================================================================
' string utils functionality
'================================================================



'*****************************************************************
' Utils_Join - join strings array to string with delimiter
' Returns a new string with all data in array that
' are separated with delimiter.
' @param array As Object - strings array
' @param delim As String - delimiter
' @return As Dynamic - joined string
'*****************************************************************
Function Utils_Join(array As Object, delim = "" As String) As String
result = ""
If type(array) = "roArray" Then
For i = 0 To array.Count() - 1
item = array[i]
If NOT (LCase(type(item)) = "rostring" or LCase(type(item)) = "string") Then
item = ""
End If
If i > 0 Then
result = result + delim
End If
result = result + item
Next
End If
Return result
End Function



'================================================================
' parse functionality
'================================================================



'*****************************************************************
' Utils_ParseXML - parse string XML into object
' Checks if input is valid XML String and parse it to
' valid roXMLElement that can be used to contain an XML tree.'
' @param str As String - string to parse
' @return As Dynamic - roXmlElement object or invalid
'*****************************************************************
Function Utils_ParseXML(str As String) As dynamic
if str = invalid return invalid
xml = CreateObject("roXMLElement")
if not xml.Parse(str) return invalid
return xml
End Function
93 changes: 93 additions & 0 deletions samples/SimpleTestApp/dev/source/main.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
' ********** Copyright 2017 Roku Corp. All Rights Reserved. **********

'Channel entry point
sub RunUserInterface(args)
if args.RunTests = "true" and type(TestRunner) = "Function" then
Runner = TestRunner()
Runner.logger.SetVerbosity(2)
Runner.logger.SetEcho(true)
Runner.SetFailFast(true)
Runner.Run()
end if
end sub

' Part of channel specific logic, where you will work with some
' external resources, like REST API, etc. You may get raw data from feed, then
' parse it and return as a native BrightScript object(roAA, roArray, etc)
' with some proper Content Meta-Data structure.
'
' If you will have a complex parsing process with a lot of external resourses,
' then it will be a good practice to move all logic to separate files.
Function GetApiArray()
url = CreateObject("roUrlTransfer")
'External resource
url.SetUrl("http://api.delvenetworks.com/rest/organizations/59021fabe3b645968e382ac726cd6c7b/channels/1cfd09ab38e54f48be8498e0249f5c83/media.rss")
rsp = url.GetToString()

'Utility function for XML parsing.
'Bassed on native Bright Script XML parser.
responseXML = Utils_ParseXML(rsp)
If responseXML <> invalid then
responseXML = responseXML.GetChildElements()
responseArray = responseXML.GetChildElements()
End if

'The result will be roArray object.
result = []

if responseArray <> invalid AND GetInterface(responseArray, "ifArray") <> invalid then
'Work with parsed XML and add to roArray some data.
for each xmlItem in responseArray
if xmlItem.getName() = "item"
itemAA = xmlItem.GetChildElements()
if itemAA <> invalid
item = {}
for each xmlItem in itemAA
if xmlItem.getName() = "media:content"
item.stream = {url : xmlItem.getAttributes().url}
item.url = xmlItem.getAttributes().url
item.streamFormat = "mp4"
mediaContent = xmlItem.GetChildElements()
for each mediaContentItem in mediaContent
if mediaContentItem.getName() = "media:thumbnail"
item.HDPosterUrl = mediaContentItem.getattributes().url
item.hdBackgroundImageUrl = mediaContentItem.getattributes().url
end if
end for
else
item[xmlItem.getName()] = xmlItem.getText()
end if
end for
result.push(item)
end if
end if
end for
end if
return result
End Function

'----------------------------------------------------------------
' Prepends a prefix to every entry in Assoc Array
'
' @return An Assoc Array with new values if all values are Strings
' or invalid if one or more value is not String.
'----------------------------------------------------------------
Function AddPrefixToAAItems(AssocArray as Object) as Object
prefix = "prefix__"

for each key in AssocArray
'Get current item
item = AssocArray[key]

'Check if current item is string
if GetInterface(item, "ifString") <> invalid then
'Prepend a prefix to current item
item = prefix + item
else
'Return invalid if item is not string
return invalid
end if
end for

return AssocArray
End Function
7 changes: 7 additions & 0 deletions samples/SimpleTestApp/dev/source/testFramework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1. Run import_unit_test_framework.bat or ./import_unit_test_framework.sh or
place the UnitTestFramework.brs file to the testFramework folder manually.
2. Sideload the app to the box.
3. To run the tests, issue the following ECP command:
curl -d '' 'http://{Roku Device IP Address}:8060/launch/dev?RunTests=true'

Documentation: https://github.com/rokudev/unit-testing-framework
Loading

0 comments on commit 79452b4

Please sign in to comment.