Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { AudioView, LabelStudio, Paragraphs } from "@humansignal/frontend-test/helpers/LSF";
import { Network } from "@humansignal/frontend-test/helpers/utils";
import { fullOpossumSnowData, videoAudioParagraphsConfig } from "../../../data/sync/video-audio-paragraphs";
 
// Local type extensions for this test
type TestWindow = Cypress.AUTWindow & {
  _wasBuffered?: boolean;
  _playedPhrases?: Set<number>;
  _totalPhrases?: number;
};
 
describe("Sync buffering playback", () => {
  beforeEach(() => {
    LabelStudio.addFeatureFlagsOnPageLoad({
      fflag_fix_front_fit_31_synced_media_buffering: true,
      fflag_feat_front_lsdv_e_278_contextual_scrolling_short: true,
    });
    Network.disableBrowserCache();
    cy.reload(true);
    cy.on("uncaught:exception", () => false);
  });
 
  afterEach(() => {
    Network.clearAllThrottles();
    Network.enableBrowserCache();
  });
 
  it.skip("should go though all paragraphs during playback with buffering", () => {
    let attempts = 3;
    const testScenario = () => {
      LabelStudio.params().config(videoAudioParagraphsConfig).data(fullOpossumSnowData).withResult([]).init();
 
      LabelStudio.waitForObjectsReady();
      AudioView.isReady();
      Paragraphs.mediaElement.should("exist");
 
      cy.window().then((win: TestWindow) => {
        const testWin = win as TestWindow;
        testWin._wasBuffered = false;
        testWin._playedPhrases = new Set();
        testWin._totalPhrases = fullOpossumSnowData.text.length;
 
        AudioView.root.then(($audioRoot) => {
          let bufferingObserver: MutationObserver | null = null;
          let buttonObserver: MutationObserver | null = null;
 
          const checkBuffering = () => {
            const bufferingIndicators = win.document.querySelectorAll(AudioView._bufferingIndicatorSelector);
            const isBuffering = bufferingIndicators.length > 0;
            if (isBuffering) {
              testWin._wasBuffered = true;
              bufferingObserver?.disconnect();
            }
          };
 
          const checkAttributeChanges = (mutations: MutationRecord[]) => {
            mutations.forEach((mutation) => {
              const button = mutation.target as HTMLButtonElement;
              if (button.getAttribute("aria-label") === "pause") {
                const phraseElement = button.parentElement?.querySelector('[data-testid^="phrase:"]');
                if (phraseElement) {
                  const phraseId = phraseElement.getAttribute("data-testid")?.replace("phrase:", "");
                  if (phraseId) {
                    testWin._playedPhrases!.add(Number.parseInt(phraseId));
                  }
                }
              }
            });
          };
 
          // Get all phrase buttons once and observe them specifically
          const phraseButtons = win.document.querySelectorAll('[class^="phraseContainer--"] button[aria-label]');
 
          const bufferingConfig = { childList: true, subtree: true };
          const attributeConfig = { attributes: true, attributeFilter: ["aria-label"] };
 
          bufferingObserver = new MutationObserver(checkBuffering);
          buttonObserver = new MutationObserver(checkAttributeChanges);
 
          bufferingObserver.observe($audioRoot[0], bufferingConfig);
 
          // Observe each phrase button individually for attribute changes
          phraseButtons.forEach((button) => {
            buttonObserver.observe(button, attributeConfig);
          });
        });
      });
 
      // Set playback speed to 2x to save some time
      AudioView.setPlaybackSpeedInput(2);
 
      // Slow down the network
      Network.throttleNetwork("/public/files/opossum_snow.mp4", 75, "throttled_mp4");
 
      AudioView.playButton.click();
 
      // Wait for audio playback to complete
      AudioView.mediaElement.its(0, { timeout: 1000 * 60 * 10 }).should(($media: any) => {
        const mediaElement = $media as HTMLMediaElement;
 
        expect(mediaElement.currentTime).to.be.greaterThan(41);
      });
 
      // Check that all phrases were played
      cy.window().then((win) => {
        const testWin = win as TestWindow;
        expect(testWin._playedPhrases!.size).to.equal(testWin._totalPhrases);
      });
    };
    testScenario();
    cy.window().then((win) => {
      const testWin = win as TestWindow;
      if (!testWin._wasBuffered && attempts-- > 1) {
        testScenario();
      }
    });
  });
});