Skip to content

Commit f6b3f22

Browse files
authored
Merge branch 'main' into allows-meta-into-parties-and-dialogs
2 parents 6017ff2 + 5e371fd commit f6b3f22

File tree

4 files changed

+138
-182
lines changed

4 files changed

+138
-182
lines changed

.github/workflows/python-package-conda.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ jobs:
3131
- name: Test with pytest
3232
run: |
3333
conda install pytest
34+
conda install pytest-mock
3435
pytest

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/vcon/dialog.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ def add_external_data(self, url: str, filename: str, mimetype: str) -> None:
175175
"""
176176
response = requests.get(url)
177177
if response.status_code == 200:
178-
self.body = response.text
179178
self.mimetype = response.headers["Content-Type"]
180179
else:
181180
raise Exception(f"Failed to fetch external data: {response.status_code}")
@@ -193,7 +192,7 @@ def add_external_data(self, url: str, filename: str, mimetype: str) -> None:
193192
# Calculate the SHA-256 hash of the body as the signature
194193
self.alg = "sha256"
195194
self.encoding = "base64url"
196-
self.signature = base64.urlsafe_b64encode(hashlib.sha256(self.body.encode()).digest()).decode()
195+
self.signature = base64.urlsafe_b64encode(hashlib.sha256(response.text.encode()).digest()).decode()
197196

198197
def add_inline_data(self, body: str, filename: str, mimetype: str) -> None:
199198
"""

tests/test_dialog.py

Lines changed: 135 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
import pytest
2-
import unittest
3-
from unittest.mock import Mock
4-
from datetime import datetime
52
from src.vcon.dialog import Dialog
6-
from src.vcon.party import PartyHistory
7-
import json
83
import hashlib
94
import base64
105

116
class TestDialog:
12-
137
# Initialization of Dialog object with all parameters
148
def test_initialization_with_all_parameters(self):
159
from datetime import datetime
@@ -88,43 +82,6 @@ def test_initialization_with_missing_optional_parameters(self):
8882
assert dialog.originator is None
8983
assert dialog.mimetype is None
9084

91-
def test_initialization_with_missing_optional_parameters(self):
92-
# Given
93-
from datetime import datetime
94-
from src.vcon.dialog import Dialog
95-
96-
dialog = Dialog(
97-
type="audio",
98-
start=datetime.now(),
99-
duration=None,
100-
parties=[1, 2],
101-
originator=None,
102-
mimetype=None,
103-
filename=None,
104-
body=None,
105-
encoding=None,
106-
url=None,
107-
alg=None,
108-
signature=None,
109-
disposition=None,
110-
party_history=None,
111-
transferee=None,
112-
transferor=None,
113-
transfer_target=None,
114-
original=None,
115-
consultation=None,
116-
target_dialog=None,
117-
campaign=None,
118-
interaction=None,
119-
skill=None
120-
)
121-
122-
# When & Then
123-
assert dialog.type == "audio"
124-
assert dialog.duration is None
125-
assert dialog.originator is None
126-
assert dialog.mimetype is None
127-
12885
def test_initialization_with_default_optional_parameters(self):
12986
# Given
13087
from datetime import datetime
@@ -176,141 +133,6 @@ def test_retrieve_dialog_mimetype_when_set(self):
176133
# When & Then
177134
assert dialog.mimetype == "video/mp4"
178135

179-
def test_initialization_with_missing_optional_parameters(self):
180-
# Given
181-
from datetime import datetime
182-
from src.vcon.dialog import Dialog
183-
184-
dialog = Dialog(
185-
type="audio",
186-
start=datetime.now(),
187-
duration=None,
188-
parties=[1, 2],
189-
originator=None,
190-
mimetype=None,
191-
filename=None,
192-
body=None,
193-
encoding=None,
194-
url=None,
195-
alg=None,
196-
signature=None,
197-
disposition=None,
198-
party_history=None,
199-
transferee=None,
200-
transferor=None,
201-
transfer_target=None,
202-
original=None,
203-
consultation=None,
204-
target_dialog=None,
205-
campaign=None,
206-
interaction=None,
207-
skill=None
208-
)
209-
210-
# When
211-
# Then
212-
assert dialog.type == "audio"
213-
assert dialog.duration is None
214-
assert dialog.originator is None
215-
assert dialog.mimetype is None
216-
217-
def test_initialization_with_default_optional_parameters(self):
218-
# Given
219-
from datetime import datetime
220-
from src.vcon.dialog import Dialog
221-
222-
dialog = Dialog(
223-
type="video",
224-
start=datetime.now(),
225-
duration=0.0,
226-
parties=[1],
227-
originator=1
228-
)
229-
230-
# When
231-
# Then
232-
assert dialog.duration == 0.0
233-
assert dialog.parties == [1]
234-
assert dialog.originator == 1
235-
236-
# Initialization of Dialog object with all parameters
237-
def test_initialization_with_all_parameters(self):
238-
from datetime import datetime
239-
from src.vcon.dialog import Dialog
240-
from src.vcon.party import PartyHistory
241-
242-
# Given
243-
party_history = [PartyHistory(1, "join", datetime.now())]
244-
dialog = Dialog(
245-
type="text",
246-
start=datetime.now(),
247-
duration=120.0,
248-
parties=[1, 2],
249-
originator=1,
250-
mimetype="text/plain",
251-
filename="example.txt",
252-
body="Hello, World!",
253-
encoding="utf-8",
254-
url="http://example.com",
255-
alg="sha256",
256-
signature="signature",
257-
disposition="inline",
258-
party_history=party_history,
259-
transferee=2,
260-
transferor=1,
261-
transfer_target=3,
262-
original=1,
263-
consultation=2,
264-
target_dialog=3,
265-
campaign="campaign1",
266-
interaction="interaction1",
267-
skill="skill1"
268-
)
269-
270-
# When & Then
271-
assert dialog.type == "text"
272-
assert dialog.duration == 120.0
273-
assert dialog.parties == [1, 2]
274-
assert dialog.party_history == party_history
275-
276-
# Initialization with missing optional parameters
277-
def test_initialization_with_missing_optional_parameters(self):
278-
from datetime import datetime
279-
from src.vcon.dialog import Dialog
280-
281-
# Given
282-
dialog = Dialog(
283-
type="audio",
284-
start=datetime.now(),
285-
duration=None,
286-
parties=[1, 2],
287-
originator=None,
288-
mimetype=None,
289-
filename=None,
290-
body=None,
291-
encoding=None,
292-
url=None,
293-
alg=None,
294-
signature=None,
295-
disposition=None,
296-
party_history=None,
297-
transferee=None,
298-
transferor=None,
299-
transfer_target=None,
300-
original=None,
301-
consultation=None,
302-
target_dialog=None,
303-
campaign=None,
304-
interaction=None,
305-
skill=None
306-
)
307-
308-
# When & Then
309-
assert dialog.type == "audio"
310-
assert dialog.duration is None
311-
assert dialog.originator is None
312-
assert dialog.mimetype is None
313-
314136
# Conversion of Dialog object to dictionary
315137
def test_conversion_to_dict(self):
316138
# Given
@@ -355,6 +177,7 @@ def test_conversion_to_dict(self):
355177
assert dialog_dict["parties"] == [1, 2]
356178
assert dialog_dict["party_history"] == [{"party": 1, "event": "join", "time": party_time}]
357179

180+
358181
# Test the meta variable in the dialog
359182
def test_meta_variable_in_dialog(self):
360183
from datetime import datetime
@@ -370,4 +193,137 @@ def test_meta_variable_in_dialog(self):
370193
assert dialog.type == type
371194
assert dialog.start == start
372195
assert dialog.parties == parties
373-
assert dialog.meta == meta
196+
assert dialog.meta == meta
197+
198+
# Successfully fetches external data from a valid URL
199+
def test_fetch_external_data_success(self, mocker):
200+
# Arrange
201+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
202+
url = "http://example.com/data"
203+
filename = "data.txt"
204+
mimetype = "text/plain"
205+
response_mock = mocker.Mock()
206+
response_mock.status_code = 200
207+
response_mock.headers = {"Content-Type": "text/plain"}
208+
response_mock.text = "sample data"
209+
mocker.patch("requests.get", return_value=response_mock)
210+
211+
# Act
212+
dialog.add_external_data(url, filename, mimetype)
213+
214+
# Assert
215+
assert dialog.mimetype == "text/plain"
216+
assert dialog.filename == filename
217+
assert dialog.alg == "sha256"
218+
assert dialog.encoding == "base64url"
219+
expected_signature = base64.urlsafe_b64encode(hashlib.sha256("sample data".encode()).digest()).decode()
220+
assert dialog.signature == expected_signature
221+
assert dialog.body is None
222+
223+
# URL returns a non-200 status code
224+
def test_fetch_external_data_failure(self, mocker):
225+
# Arrange
226+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
227+
url = "http://example.com/data"
228+
filename = "data.txt"
229+
mimetype = "text/plain"
230+
response_mock = mocker.Mock()
231+
response_mock.status_code = 404
232+
mocker.patch("requests.get", return_value=response_mock)
233+
234+
# Act & Assert
235+
with pytest.raises(Exception) as excinfo:
236+
dialog.add_external_data(url, filename, mimetype)
237+
238+
assert str(excinfo.value) == "Failed to fetch external data: 404"
239+
240+
# Correctly sets the mimetype from the response headers
241+
def test_correctly_sets_mimetype(self, mocker):
242+
# Setup
243+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
244+
url = "http://example.com/data"
245+
filename = "example_data.txt"
246+
mimetype = "text/plain"
247+
response_mock = mocker.Mock()
248+
response_mock.status_code = 200
249+
response_mock.headers = {"Content-Type": mimetype}
250+
response_mock.text = "dummy data"
251+
mocker.patch('requests.get', return_value=response_mock)
252+
253+
# Invoke
254+
dialog.add_external_data(url, filename, None)
255+
256+
# Assert
257+
assert dialog.mimetype == mimetype
258+
259+
# Overrides the filename if provided
260+
def test_overrides_filename_if_provided(self, mocker):
261+
# Setup
262+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
263+
url = "http://example.com/data"
264+
filename = "example_data.txt"
265+
new_filename = "new_data.txt"
266+
mimetype = "text/plain"
267+
response_mock = mocker.Mock()
268+
response_mock.status_code = 200
269+
response_mock.headers = {"Content-Type": mimetype}
270+
response_mock.text = "dummy data"
271+
mocker.patch('requests.get', return_value=response_mock)
272+
273+
# Invoke
274+
dialog.add_external_data(url, filename, None)
275+
dialog.add_external_data(url, new_filename, None)
276+
277+
# Assert
278+
assert dialog.filename == new_filename
279+
280+
# Correctly sets body, filename, and mimetype attributes
281+
def test_correctly_sets_attributes(self):
282+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
283+
body = "sample body"
284+
filename = "sample.txt"
285+
mimetype = "text/plain"
286+
287+
dialog.add_inline_data(body, filename, mimetype)
288+
289+
assert dialog.body == body
290+
assert dialog.filename == filename
291+
assert dialog.mimetype == mimetype
292+
293+
# Handles empty string for body
294+
def test_handles_empty_body(self):
295+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
296+
body = ""
297+
filename = "empty.txt"
298+
mimetype = "text/plain"
299+
300+
dialog.add_inline_data(body, filename, mimetype)
301+
302+
assert dialog.body == body
303+
assert dialog.filename == filename
304+
assert dialog.mimetype == mimetype
305+
assert dialog.signature == base64.urlsafe_b64encode(
306+
hashlib.sha256(body.encode()).digest()).decode()
307+
308+
# Generates a valid SHA-256 hash signature for the body
309+
def test_valid_sha256_signature(self):
310+
# Initialize the dialog object
311+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
312+
313+
# Add inline data
314+
dialog.add_inline_data("example_body", "example_filename", "text/plain")
315+
316+
# Check if the SHA-256 hash signature is valid
317+
expected_signature = base64.urlsafe_b64encode(hashlib.sha256("example_body".encode()).digest()).decode()
318+
assert dialog.signature == expected_signature
319+
320+
# Sets the encoding to "base64url"
321+
def test_encoding_base64url(self):
322+
# Initialize the dialog object
323+
dialog = Dialog(type="text", start="2023-06-01T10:00:00Z", parties=[0])
324+
325+
# Add inline data
326+
dialog.add_inline_data("example_body", "example_filename", "text/plain")
327+
328+
# Check if the encoding is set to "base64url"
329+
assert dialog.encoding == "base64url"

0 commit comments

Comments
 (0)