Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Laurent S
erp5
Commits
53108963
Commit
53108963
authored
Dec 08, 2017
by
Tomáš Peterka
Committed by
Tomáš Peterka
Dec 08, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[hal_json_style] Improve ListBox value resolution on search results
/reviewed-on
nexedi/erp5!521
parent
a17ce292
Changes
4
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
624 additions
and
97 deletions
+624
-97
bt5/erp5_configurator_standard_trade_template/bt/dependency_list
...5_configurator_standard_trade_template/bt/dependency_list
+2
-1
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
...rtal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
+443
-88
bt5/erp5_hal_json_style/TestTemplateItem/portal_components/test.erp5.testHalJsonStyle.py
...plateItem/portal_components/test.erp5.testHalJsonStyle.py
+176
-7
bt5/erp5_hal_json_style/bt/test_dependency_list
bt5/erp5_hal_json_style/bt/test_dependency_list
+3
-1
No files found.
bt5/erp5_configurator_standard_trade_template/bt/dependency_list
View file @
53108963
erp5_trade
erp5_trade
erp5_simulation
\ No newline at end of file
bt5/erp5_hal_json_style/SkinTemplateItem/portal_skins/erp5_hal_json_style/ERP5Document_getHateoas.py
View file @
53108963
This diff is collapsed.
Click to expand it.
bt5/erp5_hal_json_style/TestTemplateItem/portal_components/test.erp5.testHalJsonStyle.py
View file @
53108963
...
@@ -63,18 +63,30 @@ def simulate(script_id, params_string, code_string):
...
@@ -63,18 +63,30 @@ def simulate(script_id, params_string, code_string):
return
decorated
return
decorated
return
upperWrap
return
upperWrap
def
createIndexedDocument
():
def
wipeFolder
(
folder
):
"""Create a Foo document inside Foo module and pass it as "document" argument into wrapped function."""
folder
.
deleteContent
(
list
(
folder
.
objectIds
()))
transaction
.
commit
()
def
createIndexedDocument
(
quantity
=
1
):
"""Create `quantity` Foo document(s) in Foo module and pass it as `document(_list)` argument into the wrapped function."""
def
decorator
(
func
):
def
decorator
(
func
):
def
wrapped
(
self
,
*
args
,
**
kwargs
):
def
wrapped
(
self
,
*
args
,
**
kwargs
):
wipeFolder
(
self
.
portal
.
foo_module
)
if
quantity
<=
1
:
kwargs
.
update
(
document
=
self
.
_makeDocument
())
kwargs
.
update
(
document
=
self
.
_makeDocument
())
else
:
kwargs
.
update
(
document_list
=
[
self
.
_makeDocument
()
for
_
in
range
(
quantity
)])
self
.
portal
.
portal_caches
.
clearAllCache
()
self
.
portal
.
portal_caches
.
clearAllCache
()
self
.
tic
()
self
.
tic
()
try
:
return
func
(
self
,
*
args
,
**
kwargs
)
return
func
(
self
,
*
args
,
**
kwargs
)
finally
:
wipeFolder
(
self
.
portal
.
foo_module
)
self
.
tic
()
# unindex
return
wrapped
return
wrapped
return
decorator
return
decorator
def
do_fake_request
(
request_method
,
headers
=
None
):
def
do_fake_request
(
request_method
,
headers
=
None
,
data
=
()
):
__version__
=
"0.1"
__version__
=
"0.1"
if
(
headers
is
None
):
if
(
headers
is
None
):
headers
=
{}
headers
=
{}
...
@@ -93,7 +105,25 @@ def do_fake_request(request_method, headers=None):
...
@@ -93,7 +105,25 @@ def do_fake_request(request_method, headers=None):
env
[
'GATEWAY_INTERFACE'
]
=
'CGI/1.1 '
env
[
'GATEWAY_INTERFACE'
]
=
'CGI/1.1 '
env
[
'SCRIPT_NAME'
]
=
'Main'
env
[
'SCRIPT_NAME'
]
=
'Main'
env
.
update
(
headers
)
env
.
update
(
headers
)
return
HTTPRequest
(
StringIO
.
StringIO
(),
env
,
HTTPResponse
())
body_stream
=
StringIO
.
StringIO
()
# for some mysterious reason QUERY_STRING does not get parsed into data fields
if
data
and
request_method
.
upper
()
==
'GET'
:
# see: GET http://www.cgi101.com/book/ch3/text.html
env
[
'QUERY_STRING'
]
=
'&'
.
join
(
'{}={}'
.
format
(
urllib
.
quote_plus
(
key
),
urllib
.
quote
(
value
))
for
key
,
value
in
data
)
if
data
and
request_method
.
upper
()
==
'POST'
:
# see: POST request body https://tools.ietf.org/html/rfc1866#section-8.2.1
env
[
'CONTENT_TYPE'
]
=
'application/x-www-form-urlencoded'
for
key
,
value
in
data
:
body_stream
.
write
(
'{}={!s}&'
.
format
(
urllib
.
quote_plus
(
key
),
urllib
.
quote
(
value
)))
return
HTTPRequest
(
body_stream
,
env
,
HTTPResponse
())
from
Products.ERP5Type.tests.ERP5TypeTestCase
import
ERP5TypeTestCase
from
Products.ERP5Type.tests.ERP5TypeTestCase
import
ERP5TypeTestCase
...
@@ -952,6 +982,145 @@ class TestERP5Document_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin):
...
@@ -952,6 +982,145 @@ class TestERP5Document_getHateoas_mode_search(ERP5HALJSONStyleSkinsMixin):
mode
=
"search"
,
mode
=
"search"
,
default_param_json
=
'eyJcdTAwZWEiOiAiXHUwMGU4In0='
)
default_param_json
=
'eyJcdTAwZWEiOiAiXHUwMGU4In0='
)
@
simulate
(
'Base_getRequestUrl'
,
'*args, **kwargs'
,
'return "http://example.org/bar"'
)
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
'return "application/hal+json"'
)
@
simulate
(
'Test_listObjects'
,
'*args, **kwargs'
,
"""
from Products.PythonScripts.standard import Object
return [Object(debit_price=1000.00, credit_price=100.00),
Object(debit_price=10.00, credit_price=0.00)]
"""
)
@
simulate
(
'Test_listProducts'
,
'*args, **kwargs'
,
"""
return context.getPortalObject().foo_module.values()
"""
)
@
simulate
(
'Test_listCatalog'
,
'*args, **kwargs'
,
"""
return context.getPortalObject().portal_catalog(portal_type='Foo', sort_on=[('id', 'ASC')])
"""
)
@
createIndexedDocument
(
quantity
=
2
)
@
changeSkin
(
'Hal'
)
def
test_getHateoas_exotic_search_results
(
self
,
document_list
):
"""Test that ingestion of `list_method` result does not fail.
The only limit for the result of `list_method` is that it should be an iterable.
Practically, because we code in python, it can be any object.
"""
fake_request
=
do_fake_request
(
"GET"
)
result
=
self
.
portal
.
web_site_module
.
hateoas
.
ERP5Document_getHateoas
(
REQUEST
=
fake_request
,
mode
=
"search"
,
local_roles
=
[
"Assignor"
,
"Assignee"
],
list_method
=
'Test_listObjects'
,
select_list
=
[
'credit_price'
,
'debit_price'
]
)
self
.
assertEquals
(
fake_request
.
RESPONSE
.
status
,
200
)
self
.
assertEquals
(
fake_request
.
RESPONSE
.
getHeader
(
'Content-Type'
),
"application/hal+json"
)
result_dict
=
json
.
loads
(
result
)
self
.
assertEqual
(
len
(
result_dict
[
'_embedded'
][
'contents'
]),
2
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'debit_price'
],
1000.0
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'credit_price'
],
100.0
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
1
][
'debit_price'
],
10.0
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
1
][
'credit_price'
],
0.0
)
# Render a Document using Form Field template (only for field 'id')
result
=
self
.
portal
.
web_site_module
.
hateoas
.
ERP5Document_getHateoas
(
REQUEST
=
fake_request
,
mode
=
"search"
,
local_roles
=
[
"Assignor"
,
"Assignee"
],
list_method
=
'Test_listProducts'
,
select_list
=
[
'id'
],
form_relative_url
=
'portal_skins/erp5_ui_test/FooModule_viewFooList/listbox'
)
result_dict
=
json
.
loads
(
result
)
self
.
assertEqual
(
2
,
len
(
result_dict
[
'_embedded'
][
'contents'
]))
self
.
assertIn
(
"field_listbox"
,
result_dict
[
'_embedded'
][
'contents'
][
0
][
'id'
][
'key'
])
self
.
assertEqual
(
"StringField"
,
result_dict
[
'_embedded'
][
'contents'
][
0
][
'id'
][
'type'
])
self
.
assertEqual
(
document_list
[
0
].
getId
(),
result_dict
[
'_embedded'
][
'contents'
][
0
][
'id'
][
'default'
])
self
.
assertIn
(
"field_listbox"
,
result_dict
[
'_embedded'
][
'contents'
][
1
][
'id'
][
'key'
])
self
.
assertEqual
(
"StringField"
,
result_dict
[
'_embedded'
][
'contents'
][
1
][
'id'
][
'type'
])
self
.
assertEqual
(
document_list
[
1
].
getId
(),
result_dict
[
'_embedded'
][
'contents'
][
1
][
'id'
][
'default'
])
# Test rendering without form template of attribute, getterm and a script
result
=
self
.
portal
.
web_site_module
.
hateoas
.
ERP5Document_getHateoas
(
REQUEST
=
fake_request
,
mode
=
"search"
,
local_roles
=
[
"Assignor"
,
"Assignee"
],
list_method
=
'Test_listCatalog'
,
select_list
=
[
'title'
,
'Foo_getLocalTitle'
,
'getTotalQuantity'
]
# property, Script, method
)
result_dict
=
json
.
loads
(
result
)
self
.
assertEqual
(
len
(
result_dict
[
'_embedded'
][
'contents'
]),
2
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'title'
].
encode
(
'utf-8'
),
document_list
[
0
].
getTitle
())
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'Foo_getLocalTitle'
],
None
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'getTotalQuantity'
],
0
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
1
][
'title'
].
encode
(
'utf-8'
),
document_list
[
1
].
getTitle
())
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
1
][
'Foo_getLocalTitle'
],
None
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
1
][
'getTotalQuantity'
],
0
)
class
TestERP5PDM_getHateoas_mode_search
(
ERP5HALJSONStyleSkinsMixin
):
"""This class allows ticking for Movements to be picked up by activities."""
def
afterSetUp
(
self
):
self
.
folder
=
getattr
(
self
.
portal
,
'test_hal_json_folder'
,
None
)
if
self
.
folder
is
None
:
self
.
folder
=
self
.
portal
.
newContent
(
portal_type
=
'Folder'
,
id
=
'test_hal_json_folder'
)
self
.
vendor
=
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
title
=
"Test Vendor"
)
self
.
buyer
=
self
.
portal
.
organisation_module
.
newContent
(
portal_type
=
'Organisation'
,
title
=
"Test Buyer"
)
self
.
product
=
self
.
portal
.
product_module
.
newContent
(
portal_type
=
'Product'
,
title
=
"Resource"
)
self
.
movement
=
self
.
folder
.
newContent
(
portal_type
=
'Dummy Movement'
)
self
.
movement
.
edit
(
resource_value
=
self
.
product
,
destination_section_value
=
self
.
buyer
,
source_section_value
=
self
.
vendor
,
destination_value
=
self
.
buyer
,
source_value
=
self
.
vendor
,
)
self
.
tic
()
def
beforeTearDown
(
self
):
self
.
portal
.
organisation_module
.
deleteContent
([
self
.
buyer
.
getId
(),
self
.
vendor
.
getId
()])
self
.
portal
.
product_module
.
deleteContent
(
self
.
product
.
getId
())
wipeFolder
(
self
.
folder
)
self
.
portal
.
deleteContent
(
self
.
folder
.
getId
())
@
simulate
(
'Base_getRequestUrl'
,
'*args, **kwargs'
,
'return "http://example.org/bar"'
)
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
'return "application/hal+json"'
)
@
simulate
(
'Organisation_listInventory'
,
'*args, **kwargs'
,
"""
portal = context.getPortalObject()
return portal.portal_simulation.getInventoryList(section_uid=context.getUid())
"""
)
@
changeSkin
(
'Hal'
)
def
test_getHateoas_getInventoryasListMethod
(
self
):
"""Test that `list_method` can resolve dynamic objects from Inventory management.
This test has dependency on erp5_pdm, erp5_trade and base_trade_categories!
"""
fake_request
=
do_fake_request
(
"GET"
)
result
=
self
.
portal
.
web_site_module
.
hateoas
.
ERP5Document_getHateoas
(
REQUEST
=
fake_request
,
mode
=
"search"
,
relative_url
=
self
.
vendor
.
getRelativeUrl
(),
local_roles
=
[
"Assignor"
,
"Assignee"
],
list_method
=
'Organisation_listInventory'
,
select_list
=
[
'total_price'
,
'total_quantity'
]
)
self
.
assertEquals
(
fake_request
.
RESPONSE
.
status
,
200
)
self
.
assertEquals
(
fake_request
.
RESPONSE
.
getHeader
(
'Content-Type'
),
"application/hal+json"
)
result_dict
=
json
.
loads
(
result
)
self
.
assertEqual
(
len
(
result_dict
[
'_embedded'
][
'contents'
]),
1
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'total_price'
],
0
)
self
.
assertEqual
(
result_dict
[
'_embedded'
][
'contents'
][
0
][
'total_quantity'
],
0
)
class
TestERP5Document_getHateoas_mode_bulk
(
ERP5HALJSONStyleSkinsMixin
):
class
TestERP5Document_getHateoas_mode_bulk
(
ERP5HALJSONStyleSkinsMixin
):
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
...
@@ -963,6 +1132,7 @@ class TestERP5Document_getHateoas_mode_bulk(ERP5HALJSONStyleSkinsMixin):
...
@@ -963,6 +1132,7 @@ class TestERP5Document_getHateoas_mode_bulk(ERP5HALJSONStyleSkinsMixin):
self
.
assertEquals
(
fake_request
.
RESPONSE
.
status
,
405
)
self
.
assertEquals
(
fake_request
.
RESPONSE
.
status
,
405
)
self
.
assertEquals
(
result
,
""
)
self
.
assertEquals
(
result
,
""
)
@
simulate
(
'Base_getRequestUrl'
,
'*args, **kwargs'
,
@
simulate
(
'Base_getRequestUrl'
,
'*args, **kwargs'
,
'return "http://example.org/bar"'
)
'return "http://example.org/bar"'
)
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
...
@@ -1072,7 +1242,6 @@ class TestERP5Document_getHateoas_mode_worklist(ERP5HALJSONStyleSkinsMixin):
...
@@ -1072,7 +1242,6 @@ class TestERP5Document_getHateoas_mode_worklist(ERP5HALJSONStyleSkinsMixin):
self
.
assertEquals
(
fake_request
.
RESPONSE
.
status
,
405
)
self
.
assertEquals
(
fake_request
.
RESPONSE
.
status
,
405
)
self
.
assertEquals
(
result
,
""
)
self
.
assertEquals
(
result
,
""
)
@
simulate
(
'Base_getRequestUrl'
,
'*args, **kwargs'
,
@
simulate
(
'Base_getRequestUrl'
,
'*args, **kwargs'
,
'return "http://example.org/bar"'
)
'return "http://example.org/bar"'
)
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
@
simulate
(
'Base_getRequestHeader'
,
'*args, **kwargs'
,
...
...
bt5/erp5_hal_json_style/bt/test_dependency_list
View file @
53108963
erp5_full_text_mroonga_catalog
erp5_full_text_mroonga_catalog
erp5_ui_test_core
erp5_ui_test_core
erp5_ui_test
erp5_ui_test
erp5_dummy_movement
erp5_configurator_standard_trade_template
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment