From 04b243da43f7b53595d0cdb28f912df1641efd11 Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Wed, 27 Mar 2024 16:46:02 -0400 Subject: [PATCH 1/3] e2e: add more playback tests to assert controls work add e2e element marker --- .../src/components/controls/VideoControls.vue | 2 +- .../src/components/controls/VolumeControl.vue | 1 + tests/e2e/integration/playback.spec.ts | 78 +++++++++++++++++++ tests/e2e/support/commands.ts | 13 ++++ tests/e2e/support/index.ts | 6 ++ 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/client/src/components/controls/VideoControls.vue b/client/src/components/controls/VideoControls.vue index 3a0ca9b5c..f49ef9fc8 100644 --- a/client/src/components/controls/VideoControls.vue +++ b/client/src/components/controls/VideoControls.vue @@ -12,7 +12,7 @@ - +
diff --git a/tests/e2e/integration/playback.spec.ts b/tests/e2e/integration/playback.spec.ts index 641dcb507..ccc420074 100644 --- a/tests/e2e/integration/playback.spec.ts +++ b/tests/e2e/integration/playback.spec.ts @@ -63,4 +63,82 @@ 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.only("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); + }); + + // change the volume to 10% + cy.get('[data-cy="volume-slider"]').ottSliderMove(0.1); + cy.get("video").should(element => { + expect(element[0].volume).to.be.equal(0.1); + }); + + // 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); + }); + }); }); diff --git a/tests/e2e/support/commands.ts b/tests/e2e/support/commands.ts index d177a0d18..8e318219a 100644 --- a/tests/e2e/support/commands.ts +++ b/tests/e2e/support/commands.ts @@ -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 {}; diff --git a/tests/e2e/support/index.ts b/tests/e2e/support/index.ts index fee75f7f5..854cded28 100644 --- a/tests/e2e/support/index.ts +++ b/tests/e2e/support/index.ts @@ -28,6 +28,12 @@ declare global { ottResetRateLimit(): Chainable; ottCreateUser(userCreds: any): Chainable; ottLogin(userCreds: any): Chainable; + /** + * Helper function for moving a vue-slider component to a desired percentage. + * @param percent number between 0 and 1 + */ + ottSliderMove(percent: number): Chainable>; + ottCloseToasts(): Chainable; } } } From b2571a5f31d6c66aceb20633cd6f33e831b3f543 Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Wed, 27 Mar 2024 17:07:35 -0400 Subject: [PATCH 2/3] fix minor typo --- client/src/components/players/PlyrPlayer.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/players/PlyrPlayer.vue b/client/src/components/players/PlyrPlayer.vue index 1faac4ce0..6568b2202 100644 --- a/client/src/components/players/PlyrPlayer.vue +++ b/client/src/components/players/PlyrPlayer.vue @@ -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) => { From f1cc9b3247b17b7897aca10eb85dc73003530f3d Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Wed, 27 Mar 2024 18:15:05 -0400 Subject: [PATCH 3/3] update tests update tests --- tests/e2e/integration/playback.spec.ts | 81 ++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/tests/e2e/integration/playback.spec.ts b/tests/e2e/integration/playback.spec.ts index ccc420074..ffa6c72e0 100644 --- a/tests/e2e/integration/playback.spec.ts +++ b/tests/e2e/integration/playback.spec.ts @@ -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 @@ -93,7 +94,7 @@ describe("Video playback", () => { }); }); - it.only("should add a hls video and control it's playback rate and captions in various ways", { scrollBehavior: false }, () => { + 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(); @@ -115,10 +116,10 @@ describe("Video playback", () => { expect(element[0].playbackRate).to.be.equal(1.5); }); - // change the volume to 10% - cy.get('[data-cy="volume-slider"]').ottSliderMove(0.1); + // 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.1); + expect(element[0].volume).to.be.equal(0); }); // play the video @@ -140,5 +141,77 @@ describe("Video playback", () => { 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"); + }); + }) + });