diff --git a/.circleci/config.yml b/.circleci/config.yml index 67de915427..55e5d9289e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,22 +1,70 @@ # Check https://circleci.com/docs/2.0/language-javascript/ for more details # -version: 2.1 jobs: - build: + test: docker: - # This python image includes node 14.17.1 according to - # https://circleci.com/developer/images/image/cimg/python#image-tags - # It's a bit weird to use a python image when we care about node - # first, but it's needed to get node-gyp to work to build iltorb - - image: cimg/python:3.12.2-node + - image: cimg/node:lts-browsers + + working_directory: ~/repo + resource_class: large + steps: + - checkout - # Specify service dependencies here if necessary - # CircleCI maintains a library of pre-built images - # documented at https://circleci.com/docs/2.0/circleci-images/ - # - image: circleci/mongo:3.4.4 + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: + name: Test Jest + command: make test-jest + + - store_test_results: + path: test_reports + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + test-react: + docker: + - image: cimg/node:lts-browsers working_directory: ~/repo + parallelism: 6 + resource_class: large + steps: + - checkout + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: + name: React tests + command: make test-react + environment: + JEST_JUNIT_OUTPUT: test_reports/framer-motion-react.xml + + - store_test_results: + path: test_reports + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + test-html: + docker: + - image: cimg/node:lts-browsers + resource_class: large + working_directory: ~/repo steps: - checkout @@ -27,11 +75,30 @@ jobs: # fallback to using the latest cache if no exact match is found - v1-dependencies- - # run tests! - - run: | - make test-ci + - run: + name: HTML tests + command: make test-html + environment: + JEST_JUNIT_OUTPUT: test_reports/framer-motion-html.xml + + - run: + name: Next.js tests + command: make test-nextjs + environment: + JEST_JUNIT_OUTPUT: test_reports/framer-motion-next.xml + + - store_test_results: + path: test_reports - save_cache: paths: - node_modules key: v1-dependencies-{{ checksum "package.json" }} + +workflows: + version: 2 + build: + jobs: + - test + - test-react + - test-html diff --git a/.gitignore b/.gitignore index a0e78f76fb..65951a7bdb 100644 --- a/.gitignore +++ b/.gitignore @@ -16,8 +16,6 @@ yarn-error.log /packages/*/coverage /packages/*/cypress/screenshots /packages/*/cypress/videos -/packages/*/cypress/fixtures/appear-tests.json -/packages/*/cypress/fixtures/projection-tests.json .cache-loader .yarn/* diff --git a/.yarn/cache/jest-junit-npm-16.0.0-39a50dfe1a-412aa4bfee.zip b/.yarn/cache/jest-junit-npm-16.0.0-39a50dfe1a-412aa4bfee.zip new file mode 100644 index 0000000000..42a063e744 Binary files /dev/null and b/.yarn/cache/jest-junit-npm-16.0.0-39a50dfe1a-412aa4bfee.zip differ diff --git a/.yarn/cache/xml-npm-1.0.1-f50a7aeb8e-11b5545ef3.zip b/.yarn/cache/xml-npm-1.0.1-f50a7aeb8e-11b5545ef3.zip new file mode 100644 index 0000000000..921802a67d Binary files /dev/null and b/.yarn/cache/xml-npm-1.0.1-f50a7aeb8e-11b5545ef3.zip differ diff --git a/Makefile b/Makefile index 60b3b4f3bd..88526198bd 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,15 @@ build: bootstrap watch: bootstrap cd packages/framer-motion && yarn watch +check-status: + @BUILD_STATUS=$(shell gh api repos/framer/motion/commits/$(shell git rev-parse HEAD)/status | jq -r .state); \ + echo "Build $$BUILD_STATUS"; \ + if [ "$$BUILD_STATUS" != "success" ]; then \ + BUILD_URL=$(shell gh api repos/framer/motion/commits/$(shell git rev-parse HEAD)/status | jq -r .statuses[0].target_url); \ + echo "Build URL: $$BUILD_URL"; exit 1; \ + fi; + + test-watch: bootstrap if test -f coverage/lcov-report/index.html; then \ open coverage/lcov-report/index.html; \ @@ -61,16 +70,28 @@ test-watch: bootstrap bump: npm version patch -publish: clean bootstrap - npm publish - git push - test: bootstrap yarn test -test-ci: bootstrap +test-mkdir: mkdir -p $(TEST_REPORT_PATH) - JEST_JUNIT_OUTPUT=$(TEST_REPORT_PATH)/framer-motion.xml yarn test-ci + +test-jest: export JEST_JUNIT_OUTPUT ?= test_reports/framer-motion.xml +test-jest: bootstrap test-mkdir + echo $(JEST_JUNIT_OUTPUT) + yarn test + +test-react: build test-mkdir + yarn start-server-and-test "yarn dev-server" http://localhost:9990 "cd packages/framer-motion && cypress run --headless $(if $(CI), --spec $(shell cd packages/framer-motion && circleci tests glob "cypress/integration/*.ts" | circleci tests split), --reporter spec)" + +test-html: build test-mkdir + node dev/inc/collect-html-tests.js + yarn start-server-and-test "yarn dev-server" http://localhost:8000 "cd packages/framer-motion && cypress run --config-file=cypress.html.json $(if $(CI), --config video=false, --reporter spec)" + +test-nextjs: build test-mkdir + yarn start-server-and-test "yarn dev-server || true" http://localhost:3000 "cd packages/framer-motion && cypress run --headless --config-file=cypress.rsc.json $(if $(CI), --config video=false, --reporter spec)" + +test-e2e: test-nextjs test-html test-react lint: bootstrap yarn lint @@ -78,4 +99,4 @@ lint: bootstrap pretty: bootstrap prettier --write */**/*.tsx */**/*.ts -.PHONY: dev lint +.PHONY: dev lint test-e2e diff --git a/dev/html/public/projection/animate-nested-scale-correction.html b/dev/html/public/projection/animate-nested-scale-correction.html index 5054db72c4..1c303c034a 100644 --- a/dev/html/public/projection/animate-nested-scale-correction.html +++ b/dev/html/public/projection/animate-nested-scale-correction.html @@ -95,7 +95,7 @@ matchViewportBox(a, aOrigin) }) }) - }, 120) + }, 150) }) }) diff --git a/dev/inc/collect-html-tests.js b/dev/inc/collect-html-tests.js index 0dd813d1f8..b36541ed36 100644 --- a/dev/inc/collect-html-tests.js +++ b/dev/inc/collect-html-tests.js @@ -15,13 +15,16 @@ function collect(sourceDir, outputFile) { "utf8", (err) => { if (err) { - return console.error("Fail to collect HTML tests:", err.message) + return console.error( + `Fail to collect ${sourceDir} tests:`, + err.message + ) } - - console.log("HTML tests collected!") } ) } collect("optimized-appear", "appear-tests") collect("projection", "projection-tests") + +console.log("HTML tests collected!") diff --git a/dev/react/src/tests/layout-exit.tsx b/dev/react/src/tests/layout-exit.tsx index 826f8d0454..9400f112f0 100644 --- a/dev/react/src/tests/layout-exit.tsx +++ b/dev/react/src/tests/layout-exit.tsx @@ -19,6 +19,7 @@ export const App = () => { id="box" layout style={{ width: 100, height: 100, background: "blue" }} + transition={{ duration: 0.1 }} exit={animation} /> )} diff --git a/dev/react/src/tests/layout-shared-crossfade-a-b-transform-template.tsx b/dev/react/src/tests/layout-shared-crossfade-a-b-transform-template.tsx index 04c111ec61..10c07f666e 100644 --- a/dev/react/src/tests/layout-shared-crossfade-a-b-transform-template.tsx +++ b/dev/react/src/tests/layout-shared-crossfade-a-b-transform-template.tsx @@ -1,5 +1,5 @@ import { motion, AnimatePresence } from "framer-motion" -import { useState } from "react"; +import { useState } from "react" export const App = () => { const params = new URLSearchParams(window.location.search) @@ -27,7 +27,7 @@ export const App = () => { backgroundColor: state ? "#f00" : "#0f0", borderRadius: state ? 0 : 20, }} - transition={{ duration: 0.2, ease: () => 0.5 }} + transition={{ duration: 1, ease: () => 0.5 }} onClick={() => setState(!state)} transformTemplate={(_, generated) => `translate(-50%, -50%) ${generated}` diff --git a/dev/react/src/tests/layout-shared-crossfade-nested-display-contents.tsx b/dev/react/src/tests/layout-shared-crossfade-nested-display-contents.tsx index f9e8c98dcc..4cf1c7dab4 100644 --- a/dev/react/src/tests/layout-shared-crossfade-nested-display-contents.tsx +++ b/dev/react/src/tests/layout-shared-crossfade-nested-display-contents.tsx @@ -1,7 +1,7 @@ import { motion, AnimatePresence } from "framer-motion" -import { useState } from "react"; +import { useState } from "react" -const transition = { duration: 0.2, ease: () => 0.5 } +const transition = { duration: 0.4, ease: () => 0.5 } export const App = () => { const params = new URLSearchParams(window.location.search) const type = params.get("type") || true diff --git a/dev/react/src/tests/layout.tsx b/dev/react/src/tests/layout.tsx index 230d8f0800..9149e3cba5 100644 --- a/dev/react/src/tests/layout.tsx +++ b/dev/react/src/tests/layout.tsx @@ -1,5 +1,5 @@ import { motion, useMotionValue } from "framer-motion" -import { useState } from "react"; +import { useState } from "react" export const App = () => { const params = new URLSearchParams(window.location.search) @@ -14,7 +14,7 @@ export const App = () => { layout={type} style={{ ...(state ? a : b), backgroundColor }} onClick={() => setState(!state)} - transition={{ duration: 0.1, ease: () => 0.5 }} + transition={{ duration: 0.2, ease: () => 0.5 }} onLayoutAnimationStart={() => backgroundColor.set("green")} onLayoutAnimationComplete={() => backgroundColor.set("blue")} /> diff --git a/dev/react/src/tests/waapi-sync.tsx b/dev/react/src/tests/waapi-sync.tsx index 3216b2a304..b93f0da4d1 100644 --- a/dev/react/src/tests/waapi-sync.tsx +++ b/dev/react/src/tests/waapi-sync.tsx @@ -38,6 +38,9 @@ export const App = () => { ease: "linear", } + if (!waapiRef.current) return + if (!syncRef.current) return + const waapiAnimation = animate( waapiRef.current, { opacity: [0, 1] }, @@ -63,15 +66,23 @@ export const App = () => { ) const timeout = setTimeout(() => { - waapiStartTime.set(waapiAnimation.startTime?.toString() || "null") - syncStartTime.set(syncAnimation.startTime?.toString() || "null") + waapiStartTime.set( + waapiAnimation.startTime?.toString() || + "waapi start time not available" + ) + syncStartTime.set( + syncAnimation.startTime?.toString() || + "sync start time not available" + ) waapiExplicitStartTime.set( - waapiExplicitAnimation.startTime?.toString() || "null" + waapiExplicitAnimation.startTime?.toString() || + "waapi explicit start time not available" ) syncExplicitStartTime.set( - syncExplicitAnimation.startTime?.toString() || "null" + syncExplicitAnimation.startTime?.toString() || + "sync explicit start time not available" ) - }, 200) + }, 500) return () => { waapiAnimation.stop() diff --git a/package.json b/package.json index 0bf047db5d..516b72e385 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,10 @@ "dev-server": "turbo run dev-server", "lint": "turbo run lint", "test": "turbo run test", - "test-e2e": "turbo run test-e2e", "test-ci": "turbo run test-ci --no-cache", "measure": "turbo run measure", - "prepare": "turbo run build measure test test-e2e", "version": "yarn install && git stage yarn.lock", + "prepare": "make check-status && turbo run build measure", "new": "lerna publish from-package", "new-alpha": "turbo run build && lerna publish from-package --canary --preid alpha" }, @@ -57,6 +56,7 @@ "gsap": "^3.12.5", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "jest-junit": "^16.0.0", "jest-watch-typeahead": "^2.2.2", "lerna": "^4.0.0", "lint-staged": "^8.0.4", diff --git a/packages/framer-motion-3d/package.json b/packages/framer-motion-3d/package.json index 7a59aa5f7b..50f98d33a1 100644 --- a/packages/framer-motion-3d/package.json +++ b/packages/framer-motion-3d/package.json @@ -35,9 +35,7 @@ "scripts": { "eslint": "yarn run lint", "lint": "yarn eslint src/**/*.ts", - "test": "yarn test-unit", - "test-ci": "yarn test-unit", - "test-unit": "jest --coverage --config jest.config.json --max-workers=2", + "test": "jest --coverage --config jest.config.json --max-workers=2", "build": "yarn clean && tsc -p . && rollup -c", "dev": "yarn watch", "clean": "rm -rf types dist lib", diff --git a/packages/framer-motion/cypress.html.json b/packages/framer-motion/cypress.html.json new file mode 100644 index 0000000000..cd89b8323c --- /dev/null +++ b/packages/framer-motion/cypress.html.json @@ -0,0 +1,11 @@ +{ + "baseUrl": "http://localhost:8000", + "integrationFolder": "cypress/integration-html", + "video": true, + "screenshots": false, + "retries": 2, + "reporter": "junit", + "reporterOptions": { + "mochaFile": "../../test_reports/framer-motion-html.xml" + } +} diff --git a/packages/framer-motion/cypress.json b/packages/framer-motion/cypress.json index 54e4fcee7d..2831353e47 100644 --- a/packages/framer-motion/cypress.json +++ b/packages/framer-motion/cypress.json @@ -2,5 +2,9 @@ "baseUrl": "http://localhost:9990", "video": true, "screenshots": false, - "retries": 2 + "retries": 2, + "reporter": "junit", + "reporterOptions": { + "mochaFile": "../../test_reports/framer-motion-[hash].xml" + } } diff --git a/packages/framer-motion/cypress.rsc.json b/packages/framer-motion/cypress.rsc.json index ca31e20296..e98c255521 100644 --- a/packages/framer-motion/cypress.rsc.json +++ b/packages/framer-motion/cypress.rsc.json @@ -3,5 +3,9 @@ "integrationFolder": "cypress/integration-rsc", "video": true, "screenshots": false, - "retries": 2 + "retries": 2, + "reporter": "junit", + "reporterOptions": { + "mochaFile": "../../test_reports/framer-motion-rsc.xml" + } } diff --git a/packages/framer-motion/cypress/fixtures/example.json b/packages/framer-motion/cypress/fixtures/example.json deleted file mode 100644 index da18d9352a..0000000000 --- a/packages/framer-motion/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} \ No newline at end of file diff --git a/packages/framer-motion/cypress/fixtures/projection-tests.json b/packages/framer-motion/cypress/fixtures/projection-tests.json new file mode 100644 index 0000000000..3703bb0eb2 --- /dev/null +++ b/packages/framer-motion/cypress/fixtures/projection-tests.json @@ -0,0 +1 @@ +["animate-nested-scale-correction.html","animate-relative-instant.html","animate-relative-interrupt.html","animate-relative-mixed-transition.html","animate-relative-nested-deep.html","animate-relative-nested.html","animate-relative-parent-delayed.html","animate-relative-skip-parent.html","animate-relative.html","animate-single-element-layout-change-with-child.html","animate-single-element.html","animate-undo-layout-change.html","element-page-scroll-non-zero.html","element-scroll-layout-change.html","element-scroll-non-zero.html","element-scroll-remove.html","element-scroll-to-layout.html","element-scroll.html","fixed-child-from-static.html","fixed-child-layout-change.html","fixed-child-page-scroll-layout-change.html","fixed-child-page-scroll.html","fixed-child-to-static.html","fixed-page-scroll-layout-change.html","fixed-page-scroll.html","fixed-within-element-scroll.html","flexbox-siblings-layout-group.html","flexbox-siblings-to-grid-page-scroll-interrupt.html","flexbox-siblings-to-grid-page-scroll.html","flexbox-siblings-to-grid.html","flexbox-siblings.html","nested-layout-change-mid-projection.html","nested-layout-change-scale-correction.html","new-element-concurrent.html","perf-neighbours.html","perf-parent-child-static-grandchild.html","perf-parent-child.html","perf-shared-deep.html","perf-shared-single.html","perf-single.html","shared-block-update-promote-new.html","shared-mix-finish.html","shared-nested-promote-new-mix-interrupt.html","shared-promote-needs-reset.html","shared-promote-new-mix-interrupt.html","shared-promote-new-mix-remove.html","shared-promote-new-mix-rotate-layout.html","shared-promote-new-mix-rotate-remove.html","shared-promote-new-mix-rotate-scale-correction.html","shared-promote-new-mix-rotate.html","shared-promote-new-mix-skew.html","shared-promote-new-mix.html","shared-promote-new-rotate.html","shared-promote-new.html","shared-promote-target.html","shared-relative-new-child.html","shared-scroll-a-b-animate.html","shared-scroll-a-b.html","shared-scroll-b-a-animate.html","shared-scroll-b-a.html","shared-transform-parents-animate-2.html","shared-transform-parents-animate.html","shared-transform-parents.html","single-element-block-update.html","single-element-element-scroll-scale.html","single-element-layout-change-page-scroll.html","single-element-layout-change-perspective-container.html","single-element-layout-change-rotate-change.html","single-element-layout-change-rotate-container.html","single-element-layout-change-rotate.html","single-element-layout-change-skew-change.html","single-element-layout-change-skew-container.html","single-element-layout-change-skew.html","single-element-layout-change-with-child-page-scroll.html","single-element-layout-change-with-child-rotate-animate.html","single-element-layout-change-with-child-rotate.html","single-element-layout-change-with-child.html","single-element-layout-change.html","single-element-page-scroll-animated-overlay.html","single-element-page-scroll-overlay.html","single-element-page-scroll-scale.html","single-element-page-scroll.html","single-element-with-child-block-update.html","single-element-with-child-layout-change-interrupt.html","single-element-with-child-layout-change-page-scroll.html","single-element-with-child-layout-change.html","single-element.html","sticky-child-scroll-change-offset.html","sticky-child-scroll-change.html","sticky-child.html","sticky-element-scroll-child.html","sticky-element-scroll-shared-child.html","sticky-element-scroll.html","sticky-scroll-change-no-stick.html","sticky-scroll-change-with-stick.html","sticky-scroll-no-layout-change-stick.html","sticky-scroll-no-layout-change.html","sticky-shared-to-fixed-page-scroll-no-stick.html","sticky-shared-to-fixed-page-scroll-stick.html","sticky-to-fixed.html","transform-nested-parent-layout-change-scale-child-layout-change-transform.html","transform-nested-parent-layout-change-scale-child-layout-change.html","transform-nested-parent-scale-child-layout-change.html","transform-single-layout-change-with-scale-change.html","transform-single-layout-change-with-scale.html","transform-single-layout-change-with-translate.html","transform-single-with-scale-change.html","transform-single-with-scale.html"] \ No newline at end of file diff --git a/packages/framer-motion/cypress/integration/appear.chrome.ts b/packages/framer-motion/cypress/integration-html/appear.ts similarity index 100% rename from packages/framer-motion/cypress/integration/appear.chrome.ts rename to packages/framer-motion/cypress/integration-html/appear.ts diff --git a/packages/framer-motion/cypress/integration/projection.chrome.ts b/packages/framer-motion/cypress/integration-html/projection.ts similarity index 100% rename from packages/framer-motion/cypress/integration/projection.chrome.ts rename to packages/framer-motion/cypress/integration-html/projection.ts diff --git a/packages/framer-motion/cypress/integration/drag-to-reorder.ts b/packages/framer-motion/cypress/integration/drag-to-reorder.ts index 8e74738860..7fcabfb3cd 100644 --- a/packages/framer-motion/cypress/integration/drag-to-reorder.ts +++ b/packages/framer-motion/cypress/integration/drag-to-reorder.ts @@ -195,18 +195,19 @@ describe("Drag to reorder", () => { const delta = 20 chain = chain .trigger("pointerdown", 360, baseY, { force: true }) - .wait(50) + .wait(150) + steps.forEach((step) => { Array.from({ length: Math.abs(step) }).forEach(() => { const y = step > 0 ? delta : -delta chain = chain .trigger("pointermove", 360, baseY + y, { force: true }) - .wait(100) + .wait(150) }) }) return chain .trigger("pointerup", 360, baseY, { force: true }) - .wait(100) + .wait(150) } const chain = checkBox( diff --git a/packages/framer-motion/cypress/integration/layout-relative.chrome.ts b/packages/framer-motion/cypress/integration/layout-relative.chrome.ts deleted file mode 100644 index c89e05bd78..0000000000 --- a/packages/framer-motion/cypress/integration/layout-relative.chrome.ts +++ /dev/null @@ -1,80 +0,0 @@ -interface BoundingBox { - top: number - left: number - width: number - height: number -} - -function expectBbox(element: HTMLElement, expectedBbox: BoundingBox) { - const bbox = element.getBoundingClientRect() - expect(Math.round(bbox.left)).to.equal(expectedBbox.left) - expect(Math.round(bbox.top)).to.equal(expectedBbox.top) - expect(Math.round(bbox.width)).to.equal(expectedBbox.width) - expect(Math.round(bbox.height)).to.equal(expectedBbox.height) -} - -/** - * TODO: This isn't failing as expected - * - * if (!node.resumeFrom) { -> if (!node.resumeFrom && !hasLayoutChanged) { - * - * To see breaking behaviour. Perhaps if we could hold the second animation somehow. - */ -describe("Relative projection targets", () => { - it("If the target didn't change but the relative target changes, starts a new animation", () => { - cy.visit(`?test=layout-relative-target-change`) - .wait(50) - .get("#box") - .should(([$box]: any) => { - expectBbox($box, { - left: 0, - top: 100, - width: 80, - height: 80, - }) - }) - .get("#inner-box") - .should(([$box]: any) => { - expectBbox($box, { - left: 20, - top: 120, - height: 40, - width: 40, - }) - }) - .get("#parent") - .trigger("click") - .wait(50) - .get("#box") - .should(([$box]: any) => { - expectBbox($box, { - left: 200, - top: 100, - height: 80, - width: 80, - }) - }) - .get("#inner-box") - .should(([$box]: any) => { - expectBbox($box, { - left: 220, - top: 120, - height: 40, - width: 40, - }) - }) - // scale the box - .get("#box") - .trigger("click") - .wait(10) - .get("#inner-box") - .should(([$box]: any) => { - expectBbox($box, { - left: 220, - top: 120, - height: 40, - width: 40, - }) - }) - }) -}) diff --git a/packages/framer-motion/cypress/integration/layout-shared.ts b/packages/framer-motion/cypress/integration/layout-shared.ts index fb98d6fe62..de096f1c48 100644 --- a/packages/framer-motion/cypress/integration/layout-shared.ts +++ b/packages/framer-motion/cypress/integration/layout-shared.ts @@ -468,7 +468,7 @@ describe("Shared layout: A -> B crossfade transition", () => { }) }) .trigger("click") - .wait(10) + .wait(100) .get("#b") .should(([$box]: any) => { expectBbox($box, { @@ -480,7 +480,7 @@ describe("Shared layout: A -> B crossfade transition", () => { }) // interrupt the animation .trigger("click") - .wait(10) + .wait(100) .get("#a") .should(([$box]: any) => { expectBbox($box, { @@ -917,7 +917,7 @@ describe("Shared layout: nested crossfade transition", () => { .wait(50) .get("#a") .trigger("click") - .wait(100) + .wait(250) .get("#a") .should(([$box]: any) => { expectBbox($box, { @@ -938,7 +938,7 @@ describe("Shared layout: nested crossfade transition", () => { }) .get("#b") .trigger("click") - .wait(100) + .wait(250) .get("#b") .should(([$box]: any) => { expectBbox($box, { diff --git a/packages/framer-motion/cypress/integration/layout.ts b/packages/framer-motion/cypress/integration/layout.ts index 56c696b0bc..420b8bfee6 100644 --- a/packages/framer-motion/cypress/integration/layout.ts +++ b/packages/framer-motion/cypress/integration/layout.ts @@ -27,6 +27,7 @@ describe("Layout animation", () => { }) }) .trigger("click") + .wait(50) /** * Test that onLayoutAnimationStart fires */ @@ -45,7 +46,7 @@ describe("Layout animation", () => { /** * Test that onLayoutAnimationComplete fires */ - .wait(200) + .wait(300) .should(([$box]: any) => { expect($box.style.backgroundColor).to.equal("blue") }) diff --git a/packages/framer-motion/cypress/integration/waapi.ts b/packages/framer-motion/cypress/integration/waapi.ts index 3f5e83a2a4..4e6f833a18 100644 --- a/packages/framer-motion/cypress/integration/waapi.ts +++ b/packages/framer-motion/cypress/integration/waapi.ts @@ -78,7 +78,7 @@ describe("waapi", () => { it("Should match WAAPI and main thread startTimes, and allow explicitly setting startTime", () => { cy.visit("?test=waapi-sync") - .wait(400) + .wait(800) // Automatically recorded startTime should be the same between main thread and WAAPI .get(".auto-timer") .should(([waapi, sync]: any) => { diff --git a/packages/framer-motion/jest.config.json b/packages/framer-motion/jest.config.json index 3a1341e4b0..b064dda586 100644 --- a/packages/framer-motion/jest.config.json +++ b/packages/framer-motion/jest.config.json @@ -14,5 +14,15 @@ "watchPlugins": [ "jest-watch-typeahead/filename", "jest-watch-typeahead/testname" + ], + "reporters": [ + "default", + [ + "jest-junit", + { + "outputDirectory": "../../test_reports", + "outputName": "framer-motion.xml" + } + ] ] } diff --git a/packages/framer-motion/jest.config.ssr.json b/packages/framer-motion/jest.config.ssr.json index d6e9dc89d9..b87367e211 100644 --- a/packages/framer-motion/jest.config.ssr.json +++ b/packages/framer-motion/jest.config.ssr.json @@ -13,5 +13,15 @@ "watchPlugins": [ "jest-watch-typeahead/filename", "jest-watch-typeahead/testname" + ], + "reporters": [ + "default", + [ + "jest-junit", + { + "outputDirectory": "../../test_reports", + "outputName": "framer-motion-ssr.xml" + } + ] ] } diff --git a/packages/framer-motion/package.json b/packages/framer-motion/package.json index f16f5032e1..96ad2e5efe 100644 --- a/packages/framer-motion/package.json +++ b/packages/framer-motion/package.json @@ -74,14 +74,8 @@ "dev": "yarn watch", "clean": "rm -rf types dist lib", "test": "yarn test-server && yarn test-client", - "test-ci": "yarn test", "test-client": "jest --config jest.config.json --max-workers=2", "test-server": "jest --config jest.config.ssr.json", - "test-watch": "jest --watch --coverage --coverageReporters=lcov --config jest.config.json", - "test-e2e": "yarn test-e2e-next && yarn test-e2e-html && yarn test-e2e-react", - "test-e2e-html": "node ../../dev/inc/collect-html-tests.js && start-server-and-test 'pushd ../../; yarn dev-server; popd' http://localhost:8000 'cypress run -s cypress/integration/appear.chrome.ts --config baseUrl=http://localhost:8000/ && cypress run -s cypress/integration/projection.chrome.ts --config baseUrl=http://localhost:8000/'", - "test-e2e-react": "start-server-and-test 'pushd ../../; yarn dev-server; popd' http://localhost:9990 'cypress run --headless --config ignoreTestFiles=*.chrome.ts'", - "test-e2e-next": "start-server-and-test 'pushd ../../; yarn dev-server; popd' http://localhost:3000 'cypress run --headless --config-file=cypress.rsc.json'", "prettier": "prettier ./src/* --write", "watch": "concurrently -c blue,red -n tsc,rollup --kill-others \"tsc --watch -p . --preserveWatchOutput\" \"rollup --config --watch --no-watch.clearScreen\"", "prepack": "yarn build", diff --git a/packages/framer-motion/src/components/AnimatePresence/__tests__/AnimatePresence.test.tsx b/packages/framer-motion/src/components/AnimatePresence/__tests__/AnimatePresence.test.tsx index de5d25924f..685337b525 100644 --- a/packages/framer-motion/src/components/AnimatePresence/__tests__/AnimatePresence.test.tsx +++ b/packages/framer-motion/src/components/AnimatePresence/__tests__/AnimatePresence.test.tsx @@ -11,6 +11,7 @@ import { import { motionValue } from "../../../value" import { ResolvedValues } from "../../../render/types" import { nextFrame } from "../../../gestures/__tests__/utils" +import { waitFor } from "@testing-library/dom" describe("AnimatePresence", () => { test("Allows initial animation if no `initial` prop defined", async () => { @@ -445,7 +446,7 @@ describe("AnimatePresence", () => { }) test("Fast animations with wait render the child content correctly (strict mode disabled)", async () => { - const promise = new Promise((resolve) => { + await new Promise((resolve) => { const Component = ({ i }: { i: number }) => { return ( @@ -470,13 +471,16 @@ describe("AnimatePresence", () => { setTimeout(() => { rerender() // wait for the exit animation to check the DOM again - setTimeout(() => { - resolve(getByTestId("2").textContent === "2") - }, 150) + async function checkElement() { + await waitFor(() => + expect(getByTestId("2").textContent === "2") + ) + resolve(true) + } + + checkElement() }, 200) }) - - return await expect(promise).resolves.toBeTruthy() }) test("Elements exit in sequence during fast renders", async () => { diff --git a/yarn.lock b/yarn.lock index 29e9be0dc6..7e73b28574 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7285,6 +7285,7 @@ __metadata: gsap: ^3.12.5 jest: ^29.7.0 jest-environment-jsdom: ^29.7.0 + jest-junit: ^16.0.0 jest-watch-typeahead: ^2.2.2 lerna: ^4.0.0 lint-staged: ^8.0.4 @@ -9357,6 +9358,18 @@ __metadata: languageName: node linkType: hard +"jest-junit@npm:^16.0.0": + version: 16.0.0 + resolution: "jest-junit@npm:16.0.0" + dependencies: + mkdirp: ^1.0.4 + strip-ansi: ^6.0.1 + uuid: ^8.3.2 + xml: ^1.0.1 + checksum: 412aa4bfeec4254a9b34f417fda79107c7cbd295e56ffeb299ac9c977545910fbabe57c91c6cd1f12b700d4a1f60f79872b0075003f02da87d463e30fc2d9d78 + languageName: node + linkType: hard + "jest-leak-detector@npm:^29.7.0": version: 29.7.0 resolution: "jest-leak-detector@npm:29.7.0" @@ -15942,6 +15955,13 @@ __metadata: languageName: node linkType: hard +"xml@npm:^1.0.1": + version: 1.0.1 + resolution: "xml@npm:1.0.1" + checksum: 11b5545ef3f8fec3fa29ce251f50ad7b6c97c103ed4d851306ec23366f5fa4699dd6a942262df52313a0cd1840ab26256da253c023bad3309d8ce46fe6020ca0 + languageName: node + linkType: hard + "xmlchars@npm:^2.2.0": version: 2.2.0 resolution: "xmlchars@npm:2.2.0"