Skip to content

Commit

Permalink
e2e: add more playback integration tests (#1574)
Browse files Browse the repository at this point in the history
* e2e: add more playback tests to assert controls work
add e2e element marker

* fix minor typo

* update tests
update tests
  • Loading branch information
dyc3 authored Mar 27, 2024
1 parent 2cd2b47 commit 81d362b
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 2 deletions.
2 changes: 1 addition & 1 deletion client/src/components/controls/VideoControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<BasicControls :current-position="truePosition" />
<!-- eslint-disable-next-line vue/no-v-model-argument -->
<VolumeControl />
<TimestampDisplay :current-position="truePosition" />
<TimestampDisplay :current-position="truePosition" data-cy="timestamp-display" />
<div class="grow"><!-- Spacer --></div>
<ClosedCaptionsSwitcher
:supported="isCaptionsSupported"
Expand Down
1 change: 1 addition & 0 deletions client/src/components/controls/VolumeControl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
]
"
:drag-on-click="true"
data-cy="volume-slider"
/>
</template>

Expand Down
2 changes: 1 addition & 1 deletion client/src/components/players/PlyrPlayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ export default defineComponent({
console.info("PlyrPlayer: hls.js manifest parsed");
emit("ready");
store.commit("captions/SET_AVAILABLE_TRACKS", {
tracks: getCaptionsTracks(),
tracks: playerImpl.getCaptionsTracks(),
});
});
hls.on(Hls.Events.ERROR, (event, data) => {
Expand Down
151 changes: 151 additions & 0 deletions tests/e2e/integration/playback.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fail } from "assert";
import "cypress-iframe";

// TODO: skip this test if youtube api key is not available AND/OR create another test that uses a different video source
Expand Down Expand Up @@ -63,4 +64,154 @@ describe("Video playback", () => {
expect(element[0].paused).to.be.false;
});
});

it("should add a direct video and control it in various ways", { scrollBehavior: false }, () => {
cy.contains("button", "Add a video").scrollIntoView().click();
cy.get('[data-cy="add-preview-input"]').type("https://vjs.zencdn.net/v/oceans.mp4");
cy.get(".video button").eq(1).click();
cy.get("video").should("exist").scrollIntoView();
cy.get("video").should(element => {
expect(element[0].paused).to.be.true;
});
cy.wait(500);
// seek to some time via the seek bar
cy.get('#videoSlider').ottSliderMove(0.1);
cy.get("video").should(element => {
expect(element[0].currentTime).to.be.greaterThan(0);
})

// seek to 10 seconds via click to edit timestamp
cy.get('[data-cy="timestamp-display"] .editable').click();
cy.get('[data-cy="timestamp-display"] .editor').type("{backspace}{backspace}10{enter}")
cy.get("video").should(element => {
expect(element[0].currentTime).to.be.equal(10);
})

// change the volume to 40%
cy.get('[data-cy="volume-slider"]').ottSliderMove(0.4);
cy.get("video").should(element => {
expect(element[0].volume).to.be.equal(0.4);
});
});

it("should add a hls video and control it's playback rate and captions in various ways", { scrollBehavior: false }, () => {
cy.contains("button", "Add a video").scrollIntoView().click();
cy.get('[data-cy="add-preview-input"]').type("https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8");
cy.get(".video button").eq(1).click();
cy.get("video").should("exist").scrollIntoView();
cy.get("video").should(element => {
expect(element[0].paused).to.be.true;
});
cy.ottCloseToasts();
cy.wait(500);

// should have both captions and playback rate controls enabled
cy.get('[aria-label="Playback Speed"]').should("exist").should("be.enabled");
cy.get('[aria-label="Closed Captions"]').should("exist").should("be.enabled");

// change the playback rate to 1.5x
cy.get('[aria-label="Playback Speed"]').click();
cy.get('.v-list').contains("1.5x").click();
cy.get("video").should(element => {
expect(element[0].playbackRate).to.be.equal(1.5);
});

// FIXME: change the volume to 10%
cy.get('[data-cy="volume-slider"]').ottSliderMove(0);
cy.get("video").should(element => {
expect(element[0].volume).to.be.equal(0);
});

// play the video
cy.get(".video-controls button").eq(1).click();
cy.get("video").should("exist").should(element => {
expect(element[0].paused).to.be.false;
});

// change the playback rate to 2x
cy.get('[aria-label="Playback Speed"]').click();
cy.get('.v-list').contains("2x").click();
cy.get("video").should(element => {
expect(element[0].playbackRate).to.be.equal(2);
});

// change the playback rate to 1x
cy.get('[aria-label="Playback Speed"]').click();
cy.get('.v-list').contains("1x").click();
cy.get("video").should(element => {
expect(element[0].playbackRate).to.be.equal(1);
});

// enable captions
cy.get('[aria-label="Closed Captions"]').click();
cy.get('.v-overlay__content > .v-list').contains("en").eq(0).click();
cy.get("video").should(element => {
expect(element[0].textTracks[0].mode).to.be.equal("showing");
expect(element[0].textTracks[0].language).to.be.equal("en");
});

// disable captions
cy.get('[aria-label="Closed Captions"]').click();
cy.get('.v-list').contains("Off").click();
cy.get("video").should(element => {
expect(element[0].textTracks[0].mode).to.be.equal("disabled");
});

// show a different caption track
cy.get('[aria-label="Closed Captions"]').click();
cy.get('.v-overlay__content > .v-list').contains("es").eq(0).click();
// cy.get("video")
// .then(element => {
// for (let i = 0; i < element[0].textTracks.length; i++) {
// if (element[0].textTracks[i].kind !== "captions") {
// continue;
// }
// cy.log(JSON.stringify({
// id: element[0].textTracks[i].id,
// label: element[0].textTracks[i].label,
// language: element[0].textTracks[i].language,
// mode: element[0].textTracks[i].mode,
// kind: element[0].textTracks[i].kind,
// }));
// }
// });
cy.get("video")
.should(element => {
for (let i = 0; i < element[0].textTracks.length; i++) {
if (element[0].textTracks[i].language === "es" && element[0].textTracks[i].kind === "captions") {
expect(element[0].textTracks[i].mode).to.be.equal("showing");
return;
}
}
fail("No caption track found");
});
});

["https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8", "https://vjs.zencdn.net/v/oceans.mp4"].forEach((url, i) => {
it(`should add a couple videos and properly update the UI for things that are implemented for the current video player [${i}]`, () => {
cy.contains("button", "Add a video").scrollIntoView().click();
cy.get('[data-cy="add-preview-input"]').type("https://vimeo.com/94338566");
cy.get(".video button").eq(1).click();
cy.get('[data-cy="add-preview-input"]').type(url);
cy.get(".video button").eq(1).click();
cy.get("iframe").should("exist").scrollIntoView();
cy.wait(100);
cy.ottCloseToasts();

// should have both captions and playback rate controls disabled
cy.get('[aria-label="Playback Speed"]').should("exist").should("be.disabled");
cy.get('[aria-label="Closed Captions"]').should("exist").should("be.disabled");

// skip the video
cy.get(".video-controls button").eq(3).click();
cy.get("video").should("exist").scrollIntoView();
cy.get("video").should(element => {
expect(element[0].paused).to.be.true;
});

cy.get('[aria-label="Playback Speed"]').should("exist").should("be.enabled");
cy.get('[aria-label="Closed Captions"]').should("exist").should("be.enabled");
});
})

});
13 changes: 13 additions & 0 deletions tests/e2e/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,17 @@ Cypress.Commands.add("ottLogin", userCreds => {
});
});

Cypress.Commands.add("ottSliderMove", { prevSubject: 'element' }, (subject, percent) => {
const slider = subject[0];
const rect = slider.getBoundingClientRect();
const x = rect.width * percent;
const y = rect.height / 2;
cy.log(`Moving slider to ${percent * 100}% at x: ${x} y: ${y}`);
return cy.wrap(slider).click(x, y);
})

Cypress.Commands.add("ottCloseToasts", () => {
cy.get('[data-cy="toast-close-all"]').click();
})

export {};
6 changes: 6 additions & 0 deletions tests/e2e/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ declare global {
ottResetRateLimit(): Chainable<Element>;
ottCreateUser(userCreds: any): Chainable<Element>;
ottLogin(userCreds: any): Chainable<Element>;
/**
* Helper function for moving a vue-slider component to a desired percentage.
* @param percent number between 0 and 1
*/
ottSliderMove(percent: number): Chainable<JQuery<HTMLElement>>;
ottCloseToasts(): Chainable<Element>;
}
}
}

0 comments on commit 81d362b

Please sign in to comment.