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
20 changes: 20 additions & 0 deletions src/platform_plugin_aspects/sinks/course_overview_sink.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ def serialize_xblock(self, item, detached_xblock_types, dump_id, time_last_dumpe
"completion_mode": getattr(item, "completion_mode", ""),
}

if block_type == "video":
json_data["video_start_time"] = XBlockSink.get_seconds(
getattr(item, "start_time", None)
)
json_data["video_end_time"] = XBlockSink.get_seconds(
getattr(item, "end_time", None)
)

# Core table data, if things change here it's a big deal.
serialized_block = {
"org": course_key.org,
Expand All @@ -194,6 +202,18 @@ def serialize_xblock(self, item, detached_xblock_types, dump_id, time_last_dumpe

return serialized_block

@staticmethod
def get_seconds(value):
"""
Convert a video RelativeTime field (a timedelta) to seconds.
Args:
value: a timedelta, or None if the field is not set.
Returns: the number of seconds as a float, 0.0 if not set.
"""
if not value:
return 0.0
return value.total_seconds()

@staticmethod
def strip_branch_and_version(location):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import json
import logging
from datetime import datetime
from datetime import datetime, timedelta
from unittest.mock import MagicMock, patch

import pytest
Expand All @@ -17,6 +17,7 @@
from platform_plugin_aspects.sinks import CourseOverviewSink, XBlockSink
from platform_plugin_aspects.tasks import dump_course_to_clickhouse
from test_utils.helpers import (
FakeXBlock,
check_block_csv_matcher,
check_overview_csv_matcher,
course_factory,
Expand Down Expand Up @@ -413,3 +414,40 @@ def _check_item_serialized_location(
_check_item_serialized_location(results[31], 0, "completable")
_check_item_serialized_location(results[32], 0, "aggregator")
_check_item_serialized_location(results[33], 0, "excluded")


@pytest.mark.parametrize(
"start_time,end_time,expected_start,expected_end",
[
(timedelta(seconds=60), timedelta(seconds=240), 60.0, 240.0),
(timedelta(seconds=90.5), None, 90.5, 0.0),
(None, timedelta(seconds=30), 0.0, 30.0),
(timedelta(0), timedelta(0), 0.0, 0.0),
],
)
def test_xblock_video_clip_times(start_time, end_time, expected_start, expected_end):
"""
Test that video start and end times serialize as seconds.
"""
block = FakeXBlock("Video", block_type="video")
block.start_time = start_time
block.end_time = end_time

sink = XBlockSink(connection_overrides={}, log=MagicMock())
result = sink.serialize_xblock(block, [], "xyz", "2023-09-05")

assert result["xblock_data_json"]["video_start_time"] == expected_start
assert result["xblock_data_json"]["video_end_time"] == expected_end


def test_xblock_non_video_has_no_clip_times():
"""
Test that non-video blocks do not get video clip times.
"""
block = FakeXBlock("Problem", block_type="problem")

sink = XBlockSink(connection_overrides={}, log=MagicMock())
result = sink.serialize_xblock(block, [], "xyz", "2023-09-05")

assert "video_start_time" not in result["xblock_data_json"]
assert "video_end_time" not in result["xblock_data_json"]
Loading