From a0558eff46378e208b10f551785e0a169a0f0abc Mon Sep 17 00:00:00 2001 From: Roderick Hsiao Date: Fri, 13 Dec 2024 19:01:47 -0800 Subject: [PATCH] chore: add unit tests --- .nvmrc | 1 + eslint.config.js | 44 +++++++++ jest-config.js | 3 +- package.json | 3 +- setupTests.ts | 1 + src/__tests__/__snapshots__/index.tsx.snap | 99 ------------------- src/react-15.6/index.test.tsx | 61 ++++++++++++ src/{react-15.6.tsx => react-15.6/index.tsx} | 2 +- src/react-latest/index.test.tsx | 63 ++++++++++++ .../index.tsx} | 2 +- tsconfig.json | 1 + yarn.lock | 83 +++++++++++++--- 12 files changed, 246 insertions(+), 117 deletions(-) create mode 100644 .nvmrc create mode 100644 eslint.config.js create mode 100644 setupTests.ts delete mode 100644 src/__tests__/__snapshots__/index.tsx.snap create mode 100644 src/react-15.6/index.test.tsx rename src/{react-15.6.tsx => react-15.6/index.tsx} (97%) create mode 100644 src/react-latest/index.test.tsx rename src/{react-latest.tsx => react-latest/index.tsx} (94%) diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..5802c69 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.12.2 \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..c2e83ea --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,44 @@ +module.exports = { + extends: ['airbnb', 'airbnb-typescript'], + plugins: ['@typescript-eslint'], + parserOptions: { + ecmaFeatures: { + jsx: true, + experimentalObjectRestSpread: true, + }, + project: './tsconfig.json', + }, + rules: { + 'no-underscore-dangle': 0, + 'import/no-extraneous-dependencies': 0, + 'react/require-extension': 0, + 'react/jsx-filename-extension': 0, + 'react/destructuring-assignment': 0, + 'react/default-props-match-prop-types': 0, + 'react/jsx-props-no-spreading': 0, + 'react/static-property-placement': 0, + 'react/jsx-uses-react': 'off', + 'react/react-in-jsx-scope': 'off', + 'arrow-body-style': 0, + 'prefer-arrow-callback': 0, + 'func-names': 0, + 'react/forbid-prop-types': 0, + 'comma-dangle': 0, + 'react/sort-comp': 0, + 'react/prop-types': 0, + 'arrow-parens': 0, + 'import/extensions': [ + 'error', + 'always', + { + js: 'never', + jsx: 'never', + ts: 'never', + tsx: 'never', + }, + ], + }, + env: { + jest: true, + }, +}; diff --git a/jest-config.js b/jest-config.js index 50ea4f2..c6df666 100644 --- a/jest-config.js +++ b/jest-config.js @@ -2,5 +2,6 @@ module.exports = { transform: { '^.+\\.(jsx|tsx|js|ts)?$': 'babel-jest' }, - reporters: ['default', 'jest-junit'] + reporters: ['default', 'jest-junit'], + setupFilesAfterEnv: ['/setupTests.ts'], }; diff --git a/package.json b/package.json index febb863..54a4453 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,8 @@ "@storybook/addon-webpack5-compiler-babel": "^3.0.3", "@storybook/react": "^8.4.7", "@storybook/react-webpack5": "^8.4.7", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.1.0", "@types/jest": "^29.0.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", @@ -68,7 +70,6 @@ "jest-junit": "^15.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", - "react-test-renderer": "^19.0.0", "storybook": "^8.4.7", "ts-loader": "^9.2.8", "typescript": "^5.0.0" diff --git a/setupTests.ts b/setupTests.ts new file mode 100644 index 0000000..331666c --- /dev/null +++ b/setupTests.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; \ No newline at end of file diff --git a/src/__tests__/__snapshots__/index.tsx.snap b/src/__tests__/__snapshots__/index.tsx.snap deleted file mode 100644 index 152b9fa..0000000 --- a/src/__tests__/__snapshots__/index.tsx.snap +++ /dev/null @@ -1,99 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Aspect Ratio React < 15.6 custom style will be adopted 1`] = ` -
- demo -
-`; - -exports[`Aspect Ratio React < 15.6 should render wrapper for children 1`] = ` -
- demo -
-`; - -exports[`Aspect Ratio React < 15.6 should support number as props 1`] = ` -
- demo -
-`; - -exports[`Aspect Ratio React > 15.6 custom style will be adopted 1`] = ` -
- demo -
-`; - -exports[`Aspect Ratio React > 15.6 should render wrapper for children 1`] = ` -
- demo -
-`; - -exports[`Aspect Ratio React > 15.6 should support number as props 1`] = ` -
- demo -
-`; diff --git a/src/react-15.6/index.test.tsx b/src/react-15.6/index.test.tsx new file mode 100644 index 0000000..f8de6d7 --- /dev/null +++ b/src/react-15.6/index.test.tsx @@ -0,0 +1,61 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import AspectRatio from '.'; + +describe('AspectRatio Component (Class)', () => { + it('renders with default props', () => { + const { getByRole } = render(); + const div = getByRole('generic'); + + expect(div).toBeInTheDocument(); + expect(div).toHaveClass('react-aspect-ratio-placeholder'); + expect(div).toHaveStyle('--aspect-ratio: (1)'); + }); + + it('renders with custom className and ratio', () => { + const { getByRole } = render(); + const div = getByRole('generic'); + + expect(div).toBeInTheDocument(); + expect(div).toHaveClass('custom-class'); + expect(div).toHaveStyle('--aspect-ratio: (1.5)'); + }); + + it('applies custom styles', () => { + const { getByRole } = render(); + const div = getByRole('generic'); + + expect(div).toHaveStyle('background-color: blue'); + expect(div).toHaveStyle('--aspect-ratio: (1)'); + }); + + it('renders children correctly', () => { + const { getByText } = render( + + Test Child + + ); + + expect(getByText('Test Child')).toBeInTheDocument(); + }); + + it('updates custom property in componentDidUpdate', () => { + const { getByRole, rerender } = render(); + const div = getByRole('generic'); + + // Before update + expect(div.style.getPropertyValue('--aspect-ratio')).toBe('(1)'); + + // Update props + rerender(); + expect(div.style.getPropertyValue('--aspect-ratio')).toBe('(2)'); + }); + + it('spreads additional props onto the div', () => { + const { getByRole } = render(); + const div = getByRole('generic'); + + expect(div).toHaveAttribute('id', 'custom-id'); + expect(div).toHaveAttribute('data-testid', 'aspect-ratio'); + }); +}); diff --git a/src/react-15.6.tsx b/src/react-15.6/index.tsx similarity index 97% rename from src/react-15.6.tsx rename to src/react-15.6/index.tsx index 98b90fe..460b35d 100644 --- a/src/react-15.6.tsx +++ b/src/react-15.6/index.tsx @@ -1,6 +1,6 @@ import { Component } from 'react'; -import type { Props } from './types'; +import type { Props } from '../types'; const CUSTOM_PROPERTY_NAME = '--aspect-ratio'; const DEFAULT_CLASS_NAME = 'react-aspect-ratio-placeholder'; diff --git a/src/react-latest/index.test.tsx b/src/react-latest/index.test.tsx new file mode 100644 index 0000000..c9358cd --- /dev/null +++ b/src/react-latest/index.test.tsx @@ -0,0 +1,63 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import AspectRatio from '.'; +import { createRef } from 'react'; + +describe('AspectRatio Component', () => { + it('renders with default props', () => { + const { container } = render(); + const div = container.firstChild; + + expect(div).toBeInTheDocument(); + expect(div).toHaveClass('react-aspect-ratio-placeholder'); + expect(div).toHaveStyle('--aspect-ratio: (1)'); + }); + + it('renders with a custom className and ratio', () => { + const { container } = render( + + ); + const div = container.firstChild; + + expect(div).toBeInTheDocument(); + expect(div).toHaveClass('custom-class'); + expect(div).toHaveStyle('--aspect-ratio: (1.5)'); + }); + + it('applies custom style', () => { + const { container } = render( + + ); + const div = container.firstChild; + + expect(div).toBeInTheDocument(); + expect(div).toHaveStyle('background-color: red'); + expect(div).toHaveStyle('--aspect-ratio: (1)'); + }); + + it('renders children correctly', () => { + const { getByText } = render( + + Test Child + + ); + expect(getByText('Test Child')).toBeInTheDocument(); + }); + + it('forwards the ref correctly', () => { + const ref = createRef(); + render(); + expect(ref.current).not.toBeNull(); + expect(ref.current?.tagName).toBe('DIV'); + }); + + it('spreads additional props onto the div', () => { + const { container } = render( + + ); + const div = container.firstChild; + + expect(div).toHaveAttribute('id', 'custom-id'); + expect(div).toHaveAttribute('data-testid', 'aspect-ratio'); + }); +}); diff --git a/src/react-latest.tsx b/src/react-latest/index.tsx similarity index 94% rename from src/react-latest.tsx rename to src/react-latest/index.tsx index 0b80406..61b011a 100644 --- a/src/react-latest.tsx +++ b/src/react-latest/index.tsx @@ -1,5 +1,5 @@ import { forwardRef } from 'react'; -import type { Props } from './types'; +import type { Props } from '../types'; const CUSTOM_PROPERTY_NAME = '--aspect-ratio'; const DEFAULT_CLASS_NAME = 'react-aspect-ratio-placeholder'; diff --git a/tsconfig.json b/tsconfig.json index 932fc3f..9b74127 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "outDir": "dist", "skipLibCheck": true, "target": "ESNext", + "types": ["@testing-library/jest-dom"] }, "include": [ "src/**/*" diff --git a/yarn.lock b/yarn.lock index 99457cd..bd4d8d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" + integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -1745,6 +1750,26 @@ resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-8.4.7.tgz#c308f6a883999bd35e87826738ab8a76515932b5" integrity sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw== +"@testing-library/jest-dom@^6.6.3": + version "6.6.3" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz#26ba906cf928c0f8172e182c6fe214eb4f9f2bd2" + integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + +"@testing-library/react@^16.1.0": + version "16.1.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.1.0.tgz#aa0c61398bac82eaf89776967e97de41ac742d71" + integrity sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg== + dependencies: + "@babel/runtime" "^7.12.5" + "@types/babel__core@^7.1.14", "@types/babel__core@^7.18.0": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -2272,6 +2297,11 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + aria-query@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" @@ -2787,6 +2817,14 @@ chalk@2.1.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -3052,6 +3090,11 @@ css-what@^6.0.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -3214,6 +3257,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -4320,6 +4368,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -5336,7 +5389,7 @@ mimic-response@^2.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== -min-indent@^1.0.1: +min-indent@^1.0.0, min-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== @@ -6006,19 +6059,6 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react-is@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.0.0.tgz#d6669fd389ff022a9684f708cf6fa4962d1fea7a" - integrity sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g== - -react-test-renderer@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-19.0.0.tgz#ca6fa322c58d4bfa34635788fe242a8c3daa4c7d" - integrity sha512-oX5u9rOQlHzqrE/64CNr0HB0uWxkCQmZNSfozlYvwE71TLVgeZxVf0IjouGEr1v7r1kcDifdAJBeOhdhxsG/DA== - dependencies: - react-is "^19.0.0" - scheduler "^0.25.0" - "react@^16.8.0 || ^17.0.0 || ^18.0.0": version "18.3.1" resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" @@ -6071,6 +6111,14 @@ recast@^0.23.5: tiny-invariant "^1.3.3" tslib "^2.0.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reflect.getprototypeof@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" @@ -6604,6 +6652,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853"