diff --git a/karma.conf.js b/karma.conf.js index 45c4ff3..69f7d0e 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -32,7 +32,7 @@ module.exports = function(config) { // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['progress', "karma-typescript"], + reporters: ['dots', "karma-typescript"], // web server port @@ -59,7 +59,7 @@ module.exports = function(config) { // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits - singleRun: true, + singleRun: false, // Concurrency level // how many browser should be started simultaneous diff --git a/package.json b/package.json index 9f23a4e..84eb096 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vCarousel", - "version": "0.3.1", + "version": "0.5.0", "description": "Video carousel, a new video appears when the previous one finishes playing.", "main": "index.js", "scripts": { diff --git a/src/vCarousel.ts b/src/vCarousel.ts index 18af7a4..7902238 100644 --- a/src/vCarousel.ts +++ b/src/vCarousel.ts @@ -41,38 +41,49 @@ export class vCarousel // Il faut au moins 2 vidéos à faire tourner. this.nbVContainers=this._vContainers.length; if(this.nbVContainers < 2) - throw new Error("Il faut fournir au moins deux conteneurs de vidéo pour pouvoir faire tourner le carrousel."); + throw new Error("Il vous faut fournir au moins deux conteneurs de vidéo valides pour pouvoir lancer le carrousel."); } // Si this._firstVideoId a été fourni, on vérifie qu'il est présent dans la liste des conteneurs de vidéos. set firstVideoId(firstVideo: string) { if(firstVideo!=="" && this._vContainers.findIndex(video => video.id === firstVideo) === -1) - console.error("Vous avez fourni l'id de la vidéo à afficher en premier ("+this._firstVideoId+"), mais il n'est pas valide."); + console.error("Vous avez fourni l'id de la vidéo à afficher en premier ("+firstVideo+"), mais il n'est pas valide."); else this._firstVideoId=firstVideo; } + get firstVideoId() : string + { + return this._firstVideoId; + } + set playFirstVideo(playFirstVideo: boolean) { this._playFirstVideo=playFirstVideo; } - - set playNextVideo(playNextVideo: boolean) + + set playNextVideos(playNextVideos: boolean) { - this._playNextVideos=playNextVideo; + this._playNextVideos=playNextVideos; } set noStop(noStop: boolean) { this._noStop=noStop; } + + // transformer l'attribut pour accepter getters et setters ? + public getCurrentVideo() : HTMLMediaElement + { + return this.currentVideo; + } public run(): void { const vCarousel=this;// évite les confusions avec le "this" des événements. if(vCarousel.nbVContainers < 2) // dans le cas où on lancerait run() sans passer par le setter. - throw new Error("Il faut fournir au moins deux conteneurs valides pour faire tourner le carrousel."); + throw new Error("vCarousel ne peut être lancé sans au moins 2 vidéos."); for (let i = 0; i < vCarousel.nbVContainers; i++) { @@ -82,7 +93,7 @@ export class vCarousel vContainer.style.display = "none"; else { - // Si une vidéo est déjà visible et en cours de lecture, je la stoppe et remets à 0 + // Si une vidéo est déjà visible et en cours de lecture, je la stoppe et la remets à 0 // Sinon elle risque de continuer à être lue tout en étant cachée. if(vCarousel.currentVideo!==undefined && !vCarousel.currentVideo.paused) { diff --git a/tests/vCarouselSpec.ts b/tests/vCarouselSpec.ts new file mode 100644 index 0000000..54dc3a5 --- /dev/null +++ b/tests/vCarouselSpec.ts @@ -0,0 +1,213 @@ +import { vCarousel } from "../src/vCarousel"; + +describe("vCarousel", function() +{ + let vCarouselTest : vCarousel; + const videosWebDir="https://forge.chapril.org/Fab_Blab/vCarousel/src/branch/master/public/videos"; + const fixture="
Un clown funanbule !
Il faut forger pour devenir forgeron !
Drôle de circuit !
"; + + beforeEach(function() + { + vCarouselTest=new vCarousel(); + document.body.insertAdjacentHTML('afterbegin', fixture); + }); + + afterEach(function() + { + document.body.removeChild(document.getElementById('fixture')); + }); + + + it("should be an instance of vCarousel", function() + { + expect(vCarouselTest).toBeInstanceOf(vCarousel); + }); + + + describe("setting vCarousel", function() + { + it("Doit générer une erreur si tous les ids passés ne correspondent pas à des éléments HTML existants.", function() + { + expect(function() { return vCarouselTest.vContainers=["dontExistId","vFunanbule","vForgeron"]; }).toThrowError("Aucun élément HTML trouvé dans la page pour l'id dontExistId."); + expect(function() { return vCarouselTest.vContainers=["vFunanbule","dontExistId","vForgeron"]; }).toThrowError("Aucun élément HTML trouvé dans la page pour l'id dontExistId."); + expect(function() { return vCarouselTest.vContainers=["vFunanbule","vForgeron","dontExistId"]; }).toThrowError("Aucun élément HTML trouvé dans la page pour l'id dontExistId."); + }); + + it("Doit générer une erreur si tous les ids passés ne correspondent pas à des éléments HTML contenant une vidéo.", function() + { + expect(function() { return vCarouselTest.vContainers=["noVideo","vFunanbule","vForgeron"]; }).toThrowError("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id noVideo."); + expect(function() { return vCarouselTest.vContainers=["vFunanbule","noVideo","vForgeron"]; }).toThrowError("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id noVideo."); + expect(function() { return vCarouselTest.vContainers=["vFunanbule","vForgeron","noVideo"]; }).toThrowError("Aucune balise vidéo trouvée dans l'élément HTML ayant comme id noVideo."); + }); + + it("Doit générer une erreur s'il n'y a pas au moins deux éléments HTML valides fournis.", function() + { + expect(function() { return vCarouselTest.vContainers=["vFunanbule"]; }).toThrowError("Il vous faut fournir au moins deux conteneurs de vidéo valides pour pouvoir lancer le carrousel."); + }); + + it("Ne doit pas générer d'erreur s'il y a au moins 2 ids passés correspondant à des éléments HTML valides et contenant chacun une vidéo.", function() + { + expect(function() { return vCarouselTest.vContainers=["vFunanbule","vForgeron"]; }).not.toThrowError(); + }); + + it("Ne doit pas prendre en compte l'id fourni pour la première vidéo à afficher s'il n'est pas correcte.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron"]; + vCarouselTest.firstVideoId="vCircuit"; + expect(vCarouselTest.firstVideoId).toBeUndefined(); + }); + + it("Doit accepter un firstVideoId vide pour n'afficher aucune vidéo au lancement.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron"]; + vCarouselTest.firstVideoId=""; + expect(vCarouselTest.firstVideoId).toBe(""); + }); + }); + + describe("running vCarousel", function() + { + it("Doit générer une erreur si on lance le carrousel sans avoir fourni les éléments HTML contenant les vidéos.", function() + { + expect(function() { return vCarouselTest.run(); }).toThrowError("vCarousel ne peut être lancé sans au moins 2 vidéos."); + }); + + it("Doit cacher toutes les vidéos si cela est demandé en option, aucune vidéo n'étant enregistrée comme en cours.", function() + { + const videosId=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.vContainers=videosId; + vCarouselTest.firstVideoId=""; + vCarouselTest.run(); + for(let containerId of videosId) + { + expect(document.getElementById(containerId).style.display).toBe("none"); + } + expect(vCarouselTest.getCurrentVideo()).toBeUndefined(); + }); + + it("Doit cacher toutes les vidéos, sauf celle passée en option, qui doit être enregistrée comme celle en cours.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.firstVideoId="vCircuit"; + vCarouselTest.run(); + expect(document.getElementById("vFunanbule").style.display).toBe("none"); + expect(document.getElementById("vForgeron").style.display).toBe("none"); + expect(document.getElementById("vCircuit").style.display).toBe("block"); + let currentVideo=document.querySelector("#vCircuit video"); + expect(vCarouselTest.getCurrentVideo()).toEqual(currentVideo); + }); + + it("Doit cacher toutes les vidéos sauf la première, si aucune indication n'est passée en option, qui doit être enregistrée comme celle en cours.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.run(); + expect(document.getElementById("vFunanbule").style.display).toBe("block"); + expect(document.getElementById("vForgeron").style.display).toBe("none"); + expect(document.getElementById("vCircuit").style.display).toBe("none"); + let currentVideo=document.querySelector("#vFunanbule video"); + expect(vCarouselTest.getCurrentVideo()).toEqual(currentVideo); + }); + + it("Doit demander le lancement de la première vidéo affichée, si demandé en option.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.firstVideoId="vCircuit"; + vCarouselTest.playFirstVideo=true; + let currentVideo=document.querySelector("#vCircuit video"); + spyOn(currentVideo, "play"); + vCarouselTest.run(); + expect(currentVideo.play).toHaveBeenCalled(); + }); + + it("Ne doit demander le lancement de la première vidéo affichée, si cela n'est pas demandé en option.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.firstVideoId="vCircuit"; + let currentVideo=document.querySelector("#vCircuit video"); + spyOn(currentVideo, "play"); + vCarouselTest.run(); + expect(currentVideo.play).not.toHaveBeenCalled(); + }); + + + it("Doit passer d'une vidéo à l'autre jusqu'à ce qu'elles aient été toutes affichées.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.run(); + let currentVideo=document.querySelector("#vFunanbule video"); + + // Fin de lecture de la première vidéo, on passe à la suivante : + currentVideo.dispatchEvent(new Event("ended")); + expect(document.getElementById("vFunanbule").style.display).toBe("none"); + expect(document.getElementById("vForgeron").style.display).toBe("block"); + currentVideo=document.querySelector("#vForgeron video"); + expect(vCarouselTest.getCurrentVideo()).toEqual(currentVideo); + expect(window.location.hash).toEqual("#vForgeron"); + + // Fin de la deuxième, on passe à la dernière : + currentVideo.dispatchEvent(new Event("ended")); + expect(document.getElementById("vForgeron").style.display).toBe("none"); + expect(document.getElementById("vCircuit").style.display).toBe("block"); + currentVideo=document.querySelector("#vCircuit video"); + expect(vCarouselTest.getCurrentVideo()).toEqual(currentVideo); + expect(window.location.hash).toEqual("#vCircuit"); + + // Fin de la dernière, rien ne bouge : + currentVideo.dispatchEvent(new Event("ended")); + expect(document.getElementById("vCircuit").style.display).toBe("block"); + expect(vCarouselTest.getCurrentVideo()).toEqual(currentVideo); + expect(window.location.hash).toEqual("#vCircuit"); + }); + + it("Si demandé, le carrousel doit continuer après avoir parcouru toutes les vidéos.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.noStop=true; + vCarouselTest.run(); + let currentVideo=document.querySelector("#vFunanbule video"); + + // Fin de lecture de la première vidéo, on passe à la suivante : + currentVideo.dispatchEvent(new Event("ended")); + currentVideo=document.querySelector("#vForgeron video"); + // Fin de la deuxième, on passe à la dernière : + currentVideo.dispatchEvent(new Event("ended")); + currentVideo=document.querySelector("#vCircuit video"); + // Fin de la dernière, on retourne à la première : + currentVideo.dispatchEvent(new Event("ended")); + expect(document.getElementById("vCircuit").style.display).toBe("none"); + expect(document.getElementById("vFunanbule").style.display).toBe("block"); + currentVideo=document.querySelector("#vFunanbule video"); + expect(vCarouselTest.getCurrentVideo()).toEqual(currentVideo); + expect(window.location.hash).toEqual("#vFunanbule"); + }); + + + it("Doit demander le lancement des nouvelles vidéos affichées, si cela est demandé en option.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.playNextVideos=true; + vCarouselTest.run(); + let firstVideo=document.querySelector("#vFunanbule video"); + let nextVideo=document.querySelector("#vForgeron video"); + spyOn(nextVideo, "play"); + // Fin de lecture de la première vidéo, on passe à la suivante qui doit se lancer automatiquement : + firstVideo.dispatchEvent(new Event("ended")); + expect(nextVideo.play).toHaveBeenCalled(); + }); + + it("Ne doit pas demander le lancement des nouvelles vidéos affichées, si cela n'est pas demandé en option.", function() + { + vCarouselTest.vContainers=["vFunanbule","vForgeron","vCircuit"]; + vCarouselTest.run(); + let firstVideo=document.querySelector("#vFunanbule video"); + let nextVideo=document.querySelector("#vForgeron video"); + spyOn(nextVideo, "play"); + // Fin de lecture de la première vidéo, on passe à la suivante qui ne doit pas se lancer automatiquement : + firstVideo.dispatchEvent(new Event("ended")); + expect(nextVideo.play).not.toHaveBeenCalled(); + }); + + }); + + +}); \ No newline at end of file