Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions reflex/.templates/web/utils/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -791,9 +791,9 @@ export const hydrateClientStorage = (client_storage) => {
for (const state_key in client_storage.cookies) {
const cookie_options = client_storage.cookies[state_key];
const cookie_name = cookie_options.name || state_key;
const cookie_value = cookies.get(cookie_name);
const cookie_value = cookies.get(cookie_name, { doNotParse: true });
if (cookie_value !== undefined) {
client_storage_values[state_key] = cookies.get(cookie_name);
client_storage_values[state_key] = cookie_value;
}
}
}
Expand Down
72 changes: 72 additions & 0 deletions tests/integration/test_client_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,3 +782,75 @@ async def poll_for_c1_set():
assert l4.text == "l4 default"
assert c1s.text == ""
assert l1s.text == ""


@pytest.mark.asyncio
async def test_json_cookie_values(
client_side: AppHarness,
driver: WebDriver,
):
"""Test that JSON-formatted cookie values are preserved as strings.

Args:
client_side: harness for ClientSide app.
driver: WebDriver instance.
"""
app = client_side.app_instance
assert app is not None
assert client_side.frontend_url is not None

def poll_for_token():
token_input = AppHarness.poll_for_or_raise_timeout(
lambda: driver.find_element(By.ID, "token")
)
token = client_side.poll_for_value(token_input)
assert token is not None
return token

def set_sub(var: str, value: str):
state_var_input = driver.find_element(By.ID, "state_var")
input_value_input = driver.find_element(By.ID, "input_value")
set_sub_state_button = driver.find_element(By.ID, "set_sub_state")
AppHarness.expect(lambda: state_var_input.get_attribute("value") == "")
AppHarness.expect(lambda: input_value_input.get_attribute("value") == "")

state_var_input.send_keys(var)
input_value_input.send_keys(value)
set_sub_state_button.click()

def _assert_json_cookie_with_refresh(cookie_id: str, json_value: str):
"""Helper function to test JSON cookie values with browser refresh.

Args:
cookie_id: ID of the cookie element to manipulate.
json_value: JSON string to set as the cookie value.
"""
poll_for_token()
element = driver.find_element(By.ID, cookie_id)
set_sub(cookie_id, json_value)
AppHarness.expect(lambda: element.text == json_value)

driver.refresh()
poll_for_token()
element = driver.find_element(By.ID, cookie_id)
AppHarness.expect(lambda: element.text == json_value)

json_dict = '{"access_token": "redacted", "refresh_token": "redacted", "created_at": 1234567890, "expires_in": 3600}'
_assert_json_cookie_with_refresh("c1", json_dict)

json_array = '["item1", "item2", "item3"]'
_assert_json_cookie_with_refresh("c2", json_array)

complex_json = '{"user": {"id": 123, "name": "test"}, "settings": {"theme": "dark", "notifications": true}, "data": [1, 2, 3]}'
_assert_json_cookie_with_refresh("c1", complex_json)

json_with_escapes = (
'{"message": "Hello \\"world\\"", "path": "/api/v1", "count": 42}'
)
_assert_json_cookie_with_refresh("c2", json_with_escapes)

empty_json_obj = "{}"
_assert_json_cookie_with_refresh("c1", empty_json_obj)

empty_json_array = "[]"
_assert_json_cookie_with_refresh("c2", empty_json_array)
Loading