From fd4ef9f8c7c1c1fe20c49da77f2e94da2ebc995a Mon Sep 17 00:00:00 2001 From: Maciej Pyrc Date: Sun, 23 Jun 2024 18:47:34 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20=F0=9F=A4=96=20Update=20to=20the=20wor?= =?UTF-8?q?kflows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/docs.yml | 2 +- .github/workflows/release.yml | 46 -------- .github/workflows/tests.yml | 42 ------- .github/workflows/workflow.yml | 105 ++++++++++++++++++ __tests__/features/base/rendering.spec.tsx | 4 +- .../controls/controls.center.spec.tsx | 20 ++++ .../features/controls/controls.reset.spec.tsx | 18 +++ .../features/controls/controls.zoom.spec.tsx | 44 ++++++-- __tests__/features/pan/pan.base.spec.tsx | 25 ----- __tests__/features/pan/pan.bounds.spec.tsx | 33 ++++++ __tests__/utils/render-app.tsx | 10 +- jest.setup.ts | 12 +- src/core/instance.core.ts | 1 + 13 files changed, 223 insertions(+), 139 deletions(-) delete mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/tests.yml create mode 100644 .github/workflows/workflow.yml create mode 100644 __tests__/features/controls/controls.center.spec.tsx create mode 100644 __tests__/features/controls/controls.reset.spec.tsx create mode 100644 __tests__/features/pan/pan.bounds.spec.tsx diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 230d31fc..c8ac2333 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "20" cache: "yarn" - name: Install packages diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 96a1480c..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Release packages - -on: - push: - branches: - - master - - beta - - alpha - -defaults: - run: - shell: sh - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Wait on tests - uses: lewagon/wait-on-check-action@v1.3.1 - with: - ref: ${{ github.ref }} - check-name: "Run tests" - repo-token: ${{ secrets.GITHUB_TOKEN }} - wait-interval: 10 - - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up Node - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - - - name: Install packages - run: yarn install - - - name: Build - run: yarn build - - - name: Publish - run: yarn release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index 0d6179c0..00000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Tests - -on: push - -jobs: - tests: - name: Run tests - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: "16" - cache: "yarn" - - - name: Install packages - run: yarn install - - - name: Build - run: yarn build - - - name: Lint - run: yarn lint - - - name: Typecheck - run: yarn typecheck - - - name: Clear Jest - run: yarn jest --clearCache - - - name: Test - run: yarn test --coverage - - # - name: Send Report - # uses: paambaati/codeclimate-action@v3.0.0 - # env: - # CC_TEST_REPORTER_ID: 7d1e3713df373ab2c9efce24b85c16efa2bd953aae32bd9d278004784d71291e - # with: - # coverageLocations: ${{github.workspace}}/coverage/lcov.info:lcov diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml new file mode 100644 index 00000000..b7af66d5 --- /dev/null +++ b/.github/workflows/workflow.yml @@ -0,0 +1,105 @@ +name: Tests + +on: push + +jobs: + prepare-environment: + runs-on: ubuntu-latest + name: Prepare environment + steps: + - name: Checkout + uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: "20" + cache: "yarn" + cache-dependency-path: yarn.lock + env: + FORCE_COLOR: 0 + - name: Install node_modules on cache miss + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: yarn install --frozen-lockfile + - name: Cache node_modules + if: steps.cache-node-modules.outputs.cache-hit != 'true' + uses: actions/cache/save@v3 + with: + path: node_modules + key: yarn-${{ hashFiles('yarn.lock') }} + + tests: + name: Run tests + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: "20" + cache: "yarn" + + - name: Restore node_modules + uses: actions/cache/restore@v3 + id: cache-node-modules + with: + path: node_modules + key: yarn-${{ hashFiles('yarn.lock') }} + fail-on-cache-miss: false + - name: Install node_modules on cache miss + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: yarn install --frozen-lockfile + + - name: Build + run: yarn build + + - name: Lint + run: yarn lint + + - name: Typecheck + run: yarn typecheck + + - name: Clear Jest + run: yarn jest --clearCache + + - name: Test + run: yarn test --coverage + + # - name: Send Report + # uses: paambaati/codeclimate-action@v3.0.0 + # env: + # CC_TEST_REPORTER_ID: 7d1e3713df373ab2c9efce24b85c16efa2bd953aae32bd9d278004784d71291e + # with: + # coverageLocations: ${{github.workspace}}/coverage/lcov.info:lcov + + release: + name: Release + if: ${{ github.ref == 'refs/heads/master' }} + runs-on: ubuntu-latest + needs: tests + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: "20" + cache: "yarn" + cache-dependency-path: yarn.lock + - name: Restore node_modules + uses: actions/cache/restore@v3 + id: cache-node-modules + with: + path: node_modules + key: yarn-${{ hashFiles('yarn.lock') }} + fail-on-cache-miss: false + - name: Install node_modules on cache miss + if: steps.cache-node-modules.outputs.cache-hit != 'true' + run: yarn install --frozen-lockfile + - name: Build + run: yarn build + - name: Publish + run: yarn release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/__tests__/features/base/rendering.spec.tsx b/__tests__/features/base/rendering.spec.tsx index 9d9bdfab..1feac298 100644 --- a/__tests__/features/base/rendering.spec.tsx +++ b/__tests__/features/base/rendering.spec.tsx @@ -8,9 +8,9 @@ describe("Example view", () => { expect(wrapper).toBeDefined(); }); test("it renders center in button without errors", () => { - const { center } = renderApp(); + const { centerBtn } = renderApp(); - expect(center).toBeDefined(); + expect(centerBtn).toBeDefined(); }); test("it renders zoom in button without errors", () => { const { zoomInBtn } = renderApp(); diff --git a/__tests__/features/controls/controls.center.spec.tsx b/__tests__/features/controls/controls.center.spec.tsx new file mode 100644 index 00000000..57043cf5 --- /dev/null +++ b/__tests__/features/controls/controls.center.spec.tsx @@ -0,0 +1,20 @@ +import { fireEvent, waitFor } from "@testing-library/react"; + +import { renderApp } from "../../utils/render-app"; +import { sleep } from "../../utils"; + +describe("Controls [Center]", () => { + describe("When centering with controls button", () => { + it("should change css transform", async () => { + const { content, wrapper, centerBtn, zoom } = renderApp(); + zoom({ value: 1.65 }); + expect(content.style.transform).toBe("translate(0px, 0px) scale(1.65)"); + fireEvent(centerBtn, new MouseEvent("click", { bubbles: true })); + await waitFor(() => { + expect(content.style.transform).toBe( + "translate(-162.5px, -162.5px) scale(1.65)", + ); + }); + }); + }); +}); diff --git a/__tests__/features/controls/controls.reset.spec.tsx b/__tests__/features/controls/controls.reset.spec.tsx new file mode 100644 index 00000000..8ac4381d --- /dev/null +++ b/__tests__/features/controls/controls.reset.spec.tsx @@ -0,0 +1,18 @@ +import { fireEvent, waitFor } from "@testing-library/react"; + +import { renderApp } from "../../utils/render-app"; +import { sleep } from "../../utils"; + +describe("Controls [Reset]", () => { + describe("When resetting state with controls button", () => { + it("should change css scale", async () => { + const { content, resetBtn, zoom } = renderApp(); + zoom({ value: 1.65 }); + expect(content.style.transform).toBe("translate(0px, 0px) scale(1.65)"); + fireEvent(resetBtn, new MouseEvent("click", { bubbles: true })); + await waitFor(() => { + expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); + }); + }); + }); +}); diff --git a/__tests__/features/controls/controls.zoom.spec.tsx b/__tests__/features/controls/controls.zoom.spec.tsx index b2caa499..e5e79d82 100644 --- a/__tests__/features/controls/controls.zoom.spec.tsx +++ b/__tests__/features/controls/controls.zoom.spec.tsx @@ -1,19 +1,39 @@ import { fireEvent, waitFor } from "@testing-library/react"; import { renderApp } from "../../utils/render-app"; +import { sleep } from "../../utils"; -describe("Controls [Base]", () => { +describe("Controls [Zoom]", () => { describe("When zooming in with controls button", () => { - // it("should increase css scale with animated zoom", async () => { - // const { content, zoomInBtn } = renderApp(); - // expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); - // fireEvent(zoomInBtn, new MouseEvent("click", { bubbles: true })); - // // Animation starts - // expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); - // await waitFor(() => { - // // Animation ends - // expect(content.style.transform).toBe("translate(0px, 0px) scale(1.65)"); - // }); - // }); + it("should change css scale", async () => { + const { content, zoomInBtn, centerBtn } = renderApp(); + expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); + fireEvent(zoomInBtn, new MouseEvent("click", { bubbles: true })); + expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); + await waitFor(() => { + expect(content.style.transform).toBe( + "translate(-162.5px, -162.5px) scale(1.65)", + ); + }); + fireEvent(centerBtn, new MouseEvent("click", { bubbles: true })); + await sleep(40); + await waitFor(() => { + expect(content.style.transform).toBe( + "translate(-162.5px, -162.5px) scale(1.65)", + ); + }); + }); + }); + describe("When zooming out with controls button", () => { + it("should change css scale", async () => { + const { content, zoomOutBtn, zoom } = renderApp(); + + zoom({ value: 1.65 }); + expect(content.style.transform).toBe("translate(0px, 0px) scale(1.65)"); + fireEvent(zoomOutBtn, new MouseEvent("click", { bubbles: true })); + await waitFor(() => { + expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); + }); + }); }); }); diff --git a/__tests__/features/pan/pan.base.spec.tsx b/__tests__/features/pan/pan.base.spec.tsx index e9dec927..10b80aee 100644 --- a/__tests__/features/pan/pan.base.spec.tsx +++ b/__tests__/features/pan/pan.base.spec.tsx @@ -84,29 +84,4 @@ describe("Pan [Base]", () => { expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); }); }); - - // describe("When max position is set", () => { - // it("should not exceed max position", async () => { - // const { content, pan } = renderApp({ - // maxPositionX: 20, - // maxPositionY: 20, - // }); - // expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); - // pan({ x: 200, y: 200 }); - // expect(content.style.transform).toBe("translate(20px, 20px) scale(1)"); - // pan({ x: -20, y: -20 }); - // expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); - // }); - // it("should not exceed min position", async () => { - // const { content, pan } = renderApp({ - // minPositionX: 30, - // minPositionY: 30, - // }); - // expect(content.style.transform).toBe("translate(30px, 30px) scale(1)"); - // pan({ x: -20, y: -20 }); - // expect(content.style.transform).toBe("translate(30px, 30px) scale(1)"); - // pan({ x: 50, y: 50 }); - // expect(content.style.transform).toBe("translate(80px, 80px) scale(1)"); - // }); - // }); }); diff --git a/__tests__/features/pan/pan.bounds.spec.tsx b/__tests__/features/pan/pan.bounds.spec.tsx new file mode 100644 index 00000000..27848bfa --- /dev/null +++ b/__tests__/features/pan/pan.bounds.spec.tsx @@ -0,0 +1,33 @@ +import { waitFor } from "@testing-library/react"; + +import { renderApp } from "../../utils"; + +describe("Pan [Bounds]", () => { + it("TODO", () => { + expect(true).toBe(true); + }); + // describe("When max position is set", () => { + // it("should not exceed max position", async () => { + // const { content, pan } = renderApp({ + // maxPositionX: 20, + // maxPositionY: 20, + // }); + // expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); + // pan({ x: -200, y: -200 }); + // expect(content.style.transform).toBe("translate(20px, 20px) scale(1)"); + // pan({ x: -20, y: -20 }); + // expect(content.style.transform).toBe("translate(0px, 0px) scale(1)"); + // }); + // it("should not exceed min position", async () => { + // const { content, pan } = renderApp({ + // minPositionX: 30, + // minPositionY: 30, + // }); + // expect(content.style.transform).toBe("translate(30px, 30px) scale(1)"); + // pan({ x: -20, y: -20 }); + // expect(content.style.transform).toBe("translate(30px, 30px) scale(1)"); + // pan({ x: 50, y: 50 }); + // expect(content.style.transform).toBe("translate(80px, 80px) scale(1)"); + // }); + // }); +}); diff --git a/__tests__/utils/render-app.tsx b/__tests__/utils/render-app.tsx index 48011372..bf4460d2 100644 --- a/__tests__/utils/render-app.tsx +++ b/__tests__/utils/render-app.tsx @@ -15,7 +15,7 @@ interface RenderApp { zoomInBtn: HTMLElement; zoomOutBtn: HTMLElement; resetBtn: HTMLElement; - center: HTMLElement; + centerBtn: HTMLElement; content: HTMLElement; wrapper: HTMLElement; pan: (options: { x: number; y: number; steps?: number }) => void; @@ -112,7 +112,7 @@ export const renderApp = ({ const zoomInBtn = screen.getByTestId("zoom-in"); const zoomOutBtn = screen.getByTestId("zoom-out"); const resetBtn = screen.getByTestId("reset"); - const center = screen.getByTestId("center"); + const centerBtn = screen.getByTestId("center"); // containers const content = screen.getByTestId("content"); const wrapper = screen.getByTestId("wrapper"); @@ -131,7 +131,7 @@ export const renderApp = ({ const isZoomIn = ref.current.instance.state.scale < value; const startTime = Date.now(); - while (Date.now() - startTime < 200) { + while (Date.now() - startTime < 1000) { if ( (isZoomIn ? ref.current.instance.state.scale < value @@ -174,7 +174,7 @@ export const renderApp = ({ }); const startTime = Date.now(); - while (Date.now() - startTime < 200) { + while (Date.now() - startTime < 1000) { if ( (isZoomIn ? ref.current.instance.state.scale < value @@ -290,7 +290,7 @@ export const renderApp = ({ zoomInBtn, zoomOutBtn, resetBtn, - center, + centerBtn, content, wrapper, zoom, diff --git a/jest.setup.ts b/jest.setup.ts index f4a7ca8d..02d80f91 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -28,19 +28,19 @@ function parseTransform(transform: string): Record { ); } -const getSize = (element: HTMLElement) => { +const getSize = (element: HTMLElement, useScale: boolean) => { const isPercentageWidth = element.style.width.includes("%"); const isPercentageHeight = element.style.height.includes("%"); const values = parseTransform(element.style.transform); - const scale = values?.scale || "1"; + const scale = useScale ? values?.scale || "1" : "1"; let width = 0; let height = 0; if (isPercentageWidth || isPercentageHeight) { - const parent = getSize(element.parentNode as HTMLElement); + const parent = getSize(element.parentNode as HTMLElement, useScale); width = (parseFloat(element.style.width) * parent.width) / 100; height = (parseFloat(element.style.height) * parent.height) / 100; } else { @@ -56,7 +56,7 @@ const getSize = (element: HTMLElement) => { window.HTMLElement.prototype.getBoundingClientRect = function () { const style = window.getComputedStyle(this); - const size = getSize(this); + const size = getSize(this, true); const elements = { x: parseFloat(style.left) || 0, y: parseFloat(style.top) || 0, @@ -89,12 +89,12 @@ Object.defineProperties(window.HTMLElement.prototype, { }, offsetHeight: { get: function () { - return getSize(this).height; + return getSize(this, false).height; }, }, offsetWidth: { get: function () { - return getSize(this).width; + return getSize(this, false).width; }, }, }); diff --git a/src/core/instance.core.ts b/src/core/instance.core.ts index 9722d4e5..8b05e9be 100644 --- a/src/core/instance.core.ts +++ b/src/core/instance.core.ts @@ -200,6 +200,7 @@ export class ZoomPanPinch { } }); + // TODO: CHANGE to first interaction? // if nothing about the contentComponent has changed after 5 seconds, disconnect the observer setTimeout(() => { this.observer?.disconnect();