@@ -746,4 +746,99 @@ describe("GSAP rules", () => {
746746 const finding = result . findings . find ( ( f ) => f . code === "gsap_infinite_repeat" ) ;
747747 expect ( finding ) . toBeUndefined ( ) ;
748748 } ) ;
749+
750+ it ( "errors when CSS opacity:0 + gsap.from({opacity:0}) — invisible forever" , ( ) => {
751+ const html = `
752+ <html><body>
753+ <div data-composition-id="c1" data-width="1920" data-height="1080">
754+ <div id="title" style="opacity: 0; font-size: 120px;">Hello</div>
755+ </div>
756+ <script>
757+ window.__timelines = window.__timelines || {};
758+ const tl = gsap.timeline({ paused: true });
759+ tl.from("#title", { opacity: 0, y: 30, duration: 0.5 }, 0.2);
760+ window.__timelines["c1"] = tl;
761+ </script>
762+ </body></html>` ;
763+ const result = lintHyperframeHtml ( html ) ;
764+ const finding = result . findings . find ( ( f ) => f . code === "gsap_from_opacity_noop" ) ;
765+ expect ( finding ) . toBeDefined ( ) ;
766+ expect ( finding ! . severity ) . toBe ( "error" ) ;
767+ expect ( finding ! . selector ) . toBe ( "#title" ) ;
768+ } ) ;
769+
770+ it ( "errors when style block has opacity:0 + gsap.from({opacity:0})" , ( ) => {
771+ const html = `
772+ <html><body>
773+ <div data-composition-id="c1" data-width="1920" data-height="1080">
774+ <div id="hero">Hello</div>
775+ </div>
776+ <style>
777+ #hero { font-size: 200px; color: #fff; opacity: 0; }
778+ </style>
779+ <script>
780+ window.__timelines = window.__timelines || {};
781+ const tl = gsap.timeline({ paused: true });
782+ tl.from("#hero", { opacity: 0, scale: 3.5, duration: 0.25, ease: "expo.out" }, 0.1);
783+ window.__timelines["c1"] = tl;
784+ </script>
785+ </body></html>` ;
786+ const result = lintHyperframeHtml ( html ) ;
787+ const finding = result . findings . find ( ( f ) => f . code === "gsap_from_opacity_noop" ) ;
788+ expect ( finding ) . toBeDefined ( ) ;
789+ } ) ;
790+
791+ it ( "does NOT error when gsap.from({opacity:0}) and CSS has no opacity:0" , ( ) => {
792+ const html = `
793+ <html><body>
794+ <div data-composition-id="c1" data-width="1920" data-height="1080">
795+ <div id="title" style="font-size: 120px; color: #fff;">Hello</div>
796+ </div>
797+ <script>
798+ window.__timelines = window.__timelines || {};
799+ const tl = gsap.timeline({ paused: true });
800+ tl.from("#title", { opacity: 0, y: 30, duration: 0.5 }, 0.2);
801+ window.__timelines["c1"] = tl;
802+ </script>
803+ </body></html>` ;
804+ const result = lintHyperframeHtml ( html ) ;
805+ const finding = result . findings . find ( ( f ) => f . code === "gsap_from_opacity_noop" ) ;
806+ expect ( finding ) . toBeUndefined ( ) ;
807+ } ) ;
808+
809+ it ( "does NOT error when gsap.fromTo({opacity:0}, {opacity:1}) — destination overrides CSS" , ( ) => {
810+ const html = `
811+ <html><body>
812+ <div data-composition-id="c1" data-width="1920" data-height="1080">
813+ <div id="title" style="opacity: 0; font-size: 120px;">Hello</div>
814+ </div>
815+ <script>
816+ window.__timelines = window.__timelines || {};
817+ const tl = gsap.timeline({ paused: true });
818+ tl.fromTo("#title", { opacity: 0, y: 30 }, { opacity: 1, y: 0, duration: 0.5 }, 0.2);
819+ window.__timelines["c1"] = tl;
820+ </script>
821+ </body></html>` ;
822+ const result = lintHyperframeHtml ( html ) ;
823+ const finding = result . findings . find ( ( f ) => f . code === "gsap_from_opacity_noop" ) ;
824+ expect ( finding ) . toBeUndefined ( ) ;
825+ } ) ;
826+
827+ it ( "does NOT error when gsap.to() uses opacity:0 (exit animation)" , ( ) => {
828+ const html = `
829+ <html><body>
830+ <div data-composition-id="c1" data-width="1920" data-height="1080">
831+ <div id="title" style="opacity: 0;">Hello</div>
832+ </div>
833+ <script>
834+ window.__timelines = window.__timelines || {};
835+ const tl = gsap.timeline({ paused: true });
836+ tl.to("#title", { opacity: 0, duration: 0.5 }, 4.0);
837+ window.__timelines["c1"] = tl;
838+ </script>
839+ </body></html>` ;
840+ const result = lintHyperframeHtml ( html ) ;
841+ const finding = result . findings . find ( ( f ) => f . code === "gsap_from_opacity_noop" ) ;
842+ expect ( finding ) . toBeUndefined ( ) ;
843+ } ) ;
749844} ) ;
0 commit comments