describe('homepage hero', () => { beforeEach(() => { cy.visit('/') }) it('renders the header navigation', () => { cy.get('header.site-header').within(() => { cy.contains('Torah Media').should('be.visible') cy.contains('About').should('be.visible') cy.contains('Contact').should('be.visible') cy.contains('Donate').should('be.visible') }) }) it('opens the Torah Media page from the header navigation', () => { cy.contains('header.site-header a', 'Torah Media').click() cy.location('pathname').should('eq', '/media') cy.get('header.site-header').within(() => { cy.contains('Torah Media').should('be.visible') cy.contains('About').should('be.visible') cy.contains('Contact').should('be.visible') cy.contains('Donate').should('be.visible') }) cy.contains('h1', 'Torah Media').should('be.visible') }) it('renders the hero headline with italic emphasis', () => { cy.get('[data-cy="hero"]').within(() => { cy.contains('upgrade our lives').should('be.visible') cy.contains('em', 'healthy').should('be.visible') cy.contains('em', 'integrated').should('be.visible') cy.contains('em', 'balanced').should('be.visible') cy.contains('Torah existence').should('be.visible') cy.contains('Rabbi Yehoshua Gerzi').should('be.visible') }) }) it('renders the rabbi portrait image', () => { cy.get('[data-cy="hero-portrait"]') .should('be.visible') .and('have.attr', 'alt') .and('match', /Rabbi Yehoshua Gerzi/i) }) it('lets the rabbi portrait rise above the circular frame', () => { cy.get('[data-cy="hero-portrait"]').then( (portraitElements) => { const portraitImage = portraitElements[0] const frameElement = portraitImage.parentElement if (frameElement === null) { throw new Error('Portrait frame is missing') } const frameStyle = getComputedStyle(frameElement) expect(frameStyle.overflowX).to.equal('visible') expect(frameStyle.overflowY).to.equal('visible') expect(portraitImage.getBoundingClientRect().top).to.be.lessThan( frameElement.getBoundingClientRect().top, ) }, ) }) it('extends the circular background to the portrait base edges', () => { cy.get('[data-cy="hero-portrait"]').then( (portraitElements) => { const portraitImage = portraitElements[0] const frameElement = portraitImage.parentElement if (frameElement === null) { throw new Error('Portrait frame is missing') } const portraitBounds = portraitImage.getBoundingClientRect() const frameBounds = frameElement.getBoundingClientRect() const backgroundStyle = getComputedStyle(frameElement, '::before') const backgroundWidth = Number.parseFloat(backgroundStyle.width) const backgroundLeft = frameBounds.left + (frameBounds.width - backgroundWidth) / 2 const backgroundRight = backgroundLeft + backgroundWidth expect(backgroundStyle.content).to.not.equal('none') expect(backgroundWidth).to.be.closeTo(portraitBounds.width, 1) expect(backgroundLeft).to.be.closeTo(portraitBounds.left, 1) expect(backgroundRight).to.be.closeTo(portraitBounds.right, 1) }, ) }) }) describe('homepage discover path section', () => { beforeEach(() => { cy.visit('/') }) it('renders the heading and body copy', () => { cy.get('[data-cy="discover-path"]').within(() => { cy.contains('h2', 'Discover a Path to a Holistically Engaged Life') .should('be.visible') cy.contains('Rabbi Yehoshua Gerzi has dedicated his life') .should('be.visible') cy.contains('Healthy, Integrated and Balanced Torah Living') .should('be.visible') cy.contains('Ramat Beit Shemesh').should('be.visible') cy.contains('Pilzno Institute of Higher Learning').should('be.visible') }) }) }) describe('homepage core teachings grid', () => { beforeEach(() => { cy.visit('/') }) it('renders the heading and six teaching tiles', () => { cy.get('[data-cy="core-teachings"]').within(() => { cy.contains('h2', 'Baderech HaAvodah').should('be.visible') cy.contains('Core Teachings').should('be.visible') cy.contains('1) Introduction').should('be.visible') cy.contains('2) Foundations').should('be.visible') cy.contains('3) Divine Plan').should('be.visible') cy.contains('4) Architecture of the Soul').should('be.visible') cy.contains('5) Arba Yesodot').should('be.visible') cy.contains('6) Fluid Integration').should('be.visible') }) }) }) describe('homepage unique voice section', () => { beforeEach(() => { cy.visit('/') }) it('renders heading body and cta button', () => { cy.get('[data-cy="unique-voice"]').within(() => { cy.contains('h2', 'A Unique Voice for the Generation') .should('be.visible') cy.contains('wholly unique and much needed perspective') .should('be.visible') cy.contains('practically engaged positivity').should('be.visible') cy.contains('button', /Learn about Rabbi Gerzi.s Approach/) .should('be.visible') }) }) }) describe('homepage testimonials carousel', () => { beforeEach(() => { cy.visit('/') }) it('renders the heading and the active testimonial', () => { cy.get('[data-cy="testimonials"]').within(() => { cy.contains('h2', 'What People Are Saying').should('be.visible') cy.get('[data-cy="testimonial-active"]').within(() => { cy.contains('Nathaniel M').should('be.visible') cy.contains('best Jewish day schools').should('be.visible') }) }) }) it('shows faded half-card previews beside the active testimonial', () => { cy.viewport(1200, 800) cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-active"]').as('activeCard') cy.get('[data-cy="testimonial-previous-preview"]').as( 'previousPreview', ) cy.get('[data-cy="testimonial-next-preview"]').as('nextPreview') cy.get('[data-cy="testimonials-stage"]').as('testimonialStage') }) cy.get('@activeCard').should('be.visible') cy.get('@previousPreview').should('be.visible') cy.get('@nextPreview').should('be.visible') cy.get('@activeCard').then((activeCardElements) => { const activeOpacity = Number( getComputedStyle(activeCardElements[0]).opacity, ) cy.get('@previousPreview').then((previousPreviewElements) => { const previousPreview = previousPreviewElements[0] const previousOpacity = Number( getComputedStyle(previousPreview).opacity, ) cy.wrap(previousOpacity).should('be.lessThan', activeOpacity) }) cy.get('@nextPreview').then((nextPreviewElements) => { const nextPreview = nextPreviewElements[0] const nextOpacity = Number(getComputedStyle(nextPreview).opacity) cy.wrap(nextOpacity).should('be.lessThan', activeOpacity) }) }) cy.get('@testimonialStage').then((testimonialStageElements) => { const stageBounds = testimonialStageElements[0].getBoundingClientRect() cy.get('@previousPreview').then((previousPreviewElements) => { const previousBounds = previousPreviewElements[0].getBoundingClientRect() const previousVisibleWidth = previousBounds.right - stageBounds.left cy.wrap(previousVisibleWidth).should( 'be.closeTo', previousBounds.width / 2, 1, ) }) cy.get('@nextPreview').then((nextPreviewElements) => { const nextBounds = nextPreviewElements[0].getBoundingClientRect() const nextVisibleWidth = stageBounds.right - nextBounds.left cy.wrap(nextVisibleWidth).should( 'be.closeTo', nextBounds.width / 2, 1, ) }) }) }) it('keeps desktop cards equal sized and separated', () => { const expectedCardGap = 24 const expectedControlsGap = 12 cy.viewport(1200, 800) cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-active"]').as('activeCard') cy.get('[data-cy="testimonial-previous-preview"]').as( 'previousPreview', ) cy.get('[data-cy="testimonial-next-preview"]').as('nextPreview') cy.get('[data-cy="testimonial-prev"]') .parent() .as('testimonialControls') }) cy.get('@activeCard').then((activeCardElements) => { const activeBounds = activeCardElements[0].getBoundingClientRect() cy.get('@previousPreview').then((previousPreviewElements) => { const previousBounds = previousPreviewElements[0].getBoundingClientRect() const previousGap = activeBounds.left - previousBounds.right cy.wrap(previousBounds.height).should( 'be.closeTo', activeBounds.height, 1, ) cy.wrap(previousGap).should('be.closeTo', expectedCardGap, 1) }) cy.get('@nextPreview').then((nextPreviewElements) => { const nextBounds = nextPreviewElements[0].getBoundingClientRect() const nextGap = nextBounds.left - activeBounds.right cy.wrap(nextBounds.height).should( 'be.closeTo', activeBounds.height, 1, ) cy.wrap(nextGap).should('be.closeTo', expectedCardGap, 1) }) cy.get('@testimonialControls').then((testimonialControlsElements) => { const controlsBounds = testimonialControlsElements[0].getBoundingClientRect() const controlsGap = controlsBounds.top - activeBounds.bottom cy.wrap(controlsGap).should( 'be.closeTo', expectedControlsGap, 1, ) }) }) }) it('rounds the outer corners of clipped preview cards', () => { cy.viewport(1200, 800) cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonials-stage"]').as('testimonialStage') cy.get('[data-cy="testimonial-active"]').as('activeCard') }) cy.get('@activeCard').then((activeCardElements) => { const activeCardStyle = getComputedStyle(activeCardElements[0]) cy.get('@testimonialStage').then((testimonialStageElements) => { const testimonialStageStyle = getComputedStyle( testimonialStageElements[0], ) expect(testimonialStageStyle.borderTopLeftRadius).to.equal( activeCardStyle.borderTopLeftRadius, ) expect(testimonialStageStyle.borderTopRightRadius).to.equal( activeCardStyle.borderTopRightRadius, ) expect(testimonialStageStyle.borderBottomLeftRadius).to.equal( activeCardStyle.borderBottomLeftRadius, ) expect(testimonialStageStyle.borderBottomRightRadius).to.equal( activeCardStyle.borderBottomRightRadius, ) }) }) }) it('brings entering side previews in from the clicked direction', () => { const transitionSampleDelay = 100 const transitionSettleDelay = 1100 cy.viewport(1200, 800) cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-prev"]').click() cy.get('[data-cy="testimonial-previous-preview"]').as( 'enteringPreviousPreview', ) }) cy.wait(transitionSampleDelay) cy.get('@enteringPreviousPreview').then((previousPreviewElements) => { const earlyPreviousLeft = previousPreviewElements[0].getBoundingClientRect().left cy.wait(transitionSettleDelay) cy.get('@enteringPreviousPreview').then((finalPreviewElements) => { const finalPreviousLeft = finalPreviewElements[0].getBoundingClientRect().left expect(earlyPreviousLeft).to.be.lessThan(finalPreviousLeft) }) }) cy.visit('/') cy.viewport(1200, 800) cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-next"]').click() cy.get('[data-cy="testimonial-next-preview"]').as( 'enteringNextPreview', ) }) cy.wait(transitionSampleDelay) cy.get('@enteringNextPreview').then((nextPreviewElements) => { const earlyNextLeft = nextPreviewElements[0].getBoundingClientRect().left cy.wait(transitionSettleDelay) cy.get('@enteringNextPreview').then((finalPreviewElements) => { const finalNextLeft = finalPreviewElements[0].getBoundingClientRect().left expect(earlyNextLeft).to.be.greaterThan(finalNextLeft) }) }) }) it('hides side previews on narrow screens', () => { cy.viewport(390, 800) cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-active"]').should('be.visible') cy.get('[data-cy="testimonial-previous-preview"]') .should('not.be.visible') cy.get('[data-cy="testimonial-next-preview"]').should('not.be.visible') }) }) it('advances to the next testimonial when next is clicked', () => { cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-active"]') .should('contain.text', 'Nathaniel M') cy.get('[data-cy="testimonial-next"]').click() cy.get('[data-cy="testimonial-active"]') .should('not.contain.text', 'Nathaniel M') }) }) it('goes back to the previous testimonial when prev is clicked', () => { cy.get('[data-cy="testimonials"]').within(() => { cy.get('[data-cy="testimonial-next"]').click() cy.get('[data-cy="testimonial-prev"]').click() cy.get('[data-cy="testimonial-active"]') .should('contain.text', 'Nathaniel M') }) }) }) describe('homepage sponsor strip', () => { beforeEach(() => { cy.visit('/') }) it('renders the heading and all seven partner logos in a carousel', () => { cy.get('[data-cy="sponsors"]').within(() => { cy.contains('h2', 'Organizations Rabbi Gerzi has Worked With') .should('be.visible') const expectedAlts = [ 'SHARE', 'U of Israel', 'Mayberg Foundation', 'JLE UK', 'Yeshivat Reishit', 'Aish HaTorah', 'Yeshivat Lev HaTorah', ] cy.get('[data-cy="sponsor-logo"]').should('have.length', 7) expectedAlts.forEach((altText) => { cy.get(`[data-cy="sponsor-logo"][alt="${altText}"]`) .should('have.attr', 'src') }) cy.get('[data-cy="sponsor-carousel"]').should('be.visible') cy.get('[data-cy="sponsor-logo-duplicate"]') .should('have.length', 7) cy.get('[data-cy="sponsor-logo-duplicate"][alt=""]') .should('have.length', 7) cy.get('[data-cy="sponsor-logo-group-duplicate"]') .should('have.attr', 'aria-hidden', 'true') }) }) it('centers the carousel with side buffers and edge fades', () => { cy.viewport(1200, 900) cy.get('[data-cy="sponsors"]').within(() => { cy.get('[data-cy="sponsor-carousel"]').then((carouselElements) => { const carouselElement = carouselElements[0] const sponsorInnerElement = carouselElement.parentElement if (sponsorInnerElement === null) { throw new Error('Sponsor inner element is missing') } const carouselBounds = carouselElement.getBoundingClientRect() const sponsorInnerBounds = sponsorInnerElement.getBoundingClientRect() const leftBuffer = carouselBounds.left - sponsorInnerBounds.left const rightBuffer = sponsorInnerBounds.right - carouselBounds.right const carouselRatio = carouselBounds.width / sponsorInnerBounds.width const carouselStyle = getComputedStyle(carouselElement) const maskImage = carouselStyle.maskImage || carouselStyle.webkitMaskImage expect(carouselRatio).to.be.closeTo(0.85, 0.02) expect(leftBuffer).to.be.closeTo(rightBuffer, 1) expect(maskImage).to.contain('50px') }) }) }) it('uses the faster carousel timing', () => { cy.get('[data-cy="sponsor-track"]').then((trackElements) => { const trackStyle = getComputedStyle(trackElements[0]) expect(trackStyle.animationDuration).to.equal('20s') }) }) it('scrolls the sponsor logos from right to left', () => { cy.get('[data-cy="sponsor-track"]').then((trackElements) => { const startingLeft = trackElements[0].getBoundingClientRect().left cy.wait(750) cy.get('[data-cy="sponsor-track"]').then((laterTrackElements) => { const laterLeft = laterTrackElements[0].getBoundingClientRect().left expect(startingLeft).to.be.greaterThan(laterLeft) }) }) }) }) describe('homepage projects grid', () => { beforeEach(() => { cy.visit('/') }) it('renders the heading and four project cards', () => { cy.get('[data-cy="projects"]').within(() => { cy.contains('h2', 'Projects').should('be.visible') cy.get('[data-cy="project-card"]').should('have.length', 4) cy.contains('h3', 'Chaburot').should('be.visible') cy.contains('group learning sessions').should('be.visible') cy.contains('h3', 'Pilzno Work Inspired').should('be.visible') cy.contains('healthy relationship to work').should('be.visible') cy.contains('h3', 'Shul').should('be.visible') cy.contains('Pilzno Beis Dovid').should('be.visible') cy.contains('h3', 'New Building').should('be.visible') cy.contains('Beit Shemesh municipality').should('be.visible') }) }) }) describe('homepage start your journey ctas', () => { beforeEach(() => { cy.visit('/') }) it('renders both journey CTAs with their headings and bodies', () => { cy.get('[data-cy="journey"]').within(() => { cy.contains('h2', 'Start Your Journey').should('be.visible') cy.get('[data-cy="journey-media"]').within(() => { cy.contains('Access').should('be.visible') cy.contains('Torah Media').should('be.visible') cy.contains('wealth of video, audio and written content') .should('be.visible') }) cy.get('[data-cy="journey-baderech"]').within(() => { cy.contains('Explore').should('be.visible') cy.contains('Baderech HaAvodah').should('be.visible') cy.contains('transformative principles').should('be.visible') }) }) }) }) describe('homepage get involved and footer', () => { beforeEach(() => { cy.visit('/') }) it('renders the newsletter signup form', () => { cy.get('[data-cy="get-involved"]').within(() => { cy.contains('h2', 'Get Involved').should('be.visible') cy.contains( 'Subscribe for updates as we release new content', ).should('be.visible') cy.get('input[name="fullName"]').should('be.visible') cy.get('input[name="email"]').should('be.visible') cy.contains('button', 'Submit').should('be.visible') }) }) it('renders the footer with links and copyright', () => { cy.get('[data-cy="footer"]').within(() => { cy.contains('Torah Media').should('be.visible') cy.contains('About').should('be.visible') cy.contains('Donate').should('be.visible') cy.contains('Contact').should('be.visible') cy.contains(/Rabbi Gerzi 2025/).should('be.visible') }) }) })