diff --git a/package-lock.json b/package-lock.json index 2b65930..9f25e59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@types/node": "^18.18.5", "@vitejs/plugin-vue": "^4.4.0", "@vitest/coverage-istanbul": "^0.34.6", + "@vitest/ui": "^0.34.6", "@vue/eslint-config-prettier": "^8.0.0", "@vue/eslint-config-typescript": "^12.0.0", "@vue/test-utils": "^2.4.1", @@ -1823,6 +1824,27 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/ui": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.34.6.tgz", + "integrity": "sha512-/fxnCwGC0Txmr3tF3BwAbo3v6U2SkBTGR9UB8zo0Ztlx0BTOXHucE0gDHY7SjwEktCOHatiGmli9kZD6gYSoWQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "0.34.6", + "fast-glob": "^3.3.0", + "fflate": "^0.8.0", + "flatted": "^3.2.7", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "sirv": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": ">=0.30.1 <1" + } + }, "node_modules/@vitest/utils": { "version": "0.34.6", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", @@ -3454,6 +3476,12 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz", + "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==", + "dev": true + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", diff --git a/package.json b/package.json index f2dd9f8..56cc739 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "build": "run-p type-check \"build-only {@}\" --", "preview": "vite preview", "test:unit": "vitest", + "test:ui": "vitest --ui", + "test:update": "vitest -u", "coverage": "vitest run --coverage", "test:e2e": "playwright test", "build-only": "vite build", @@ -63,6 +65,7 @@ "@types/node": "^18.18.5", "@vitejs/plugin-vue": "^4.4.0", "@vitest/coverage-istanbul": "^0.34.6", + "@vitest/ui": "^0.34.6", "@vue/eslint-config-prettier": "^8.0.0", "@vue/eslint-config-typescript": "^12.0.0", "@vue/test-utils": "^2.4.1", diff --git a/src/components/BuiButton/BuiButton.spec.ts b/src/components/BuiButton/BuiButton.spec.ts index 1135746..119ab60 100644 --- a/src/components/BuiButton/BuiButton.spec.ts +++ b/src/components/BuiButton/BuiButton.spec.ts @@ -5,11 +5,12 @@ import { ButtonColor } from './types' import type { TestWrapper } from '../../types/globalTypes' describe('BuiButton', () => { - // @ts-ignore + // @ts-ignore-next-line let wrapper: TestWrapper const createComponent = (props: { props: { + disabled?: boolean color: ButtonColor } }) => { @@ -18,25 +19,41 @@ describe('BuiButton', () => { ...props }) } - test('default button classes is correct', () => { + test('default button snapshot', async () => { createComponent({ props: { color: 'primary' } }) - - expect(wrapper.classes().join(' ')).toEqual( - 'focus:ring-4 focus:ring-primary-200 font-medium rounded text-sm px-5 py-2.5 mr-2 mb-2 focus:outline-none bg-primary-500 hover:bg-primary-550 dark:bg-primary-500 dark:hover:bg-primary-600 dark:focus:ring-primary-400 text-white' - ) + const result = wrapper.html() + await expect(result).toMatchFileSnapshot('./test/default.output.html') + }) + test('default disabled button snapshot', async () => { + createComponent({ props: { color: 'primary', disabled: true } }) + const result = wrapper.html() + await expect(result).toMatchFileSnapshot('./test/default-disabled.output.html') }) - test('secondary button classes is correct', () => { + + test('secondary button classes is correct', async () => { createComponent({ props: { color: 'secondary' } }) - expect(wrapper.classes().join(' ')).toEqual( - 'focus:ring-4 focus:ring-primary-200 font-medium rounded text-sm px-5 py-2.5 mr-2 mb-2 focus:outline-none bg-primary-150 hover:bg-primary-200 dark:bg-primary-650 dark:hover:bg-primary-700 dark:focus:ring-primary-300 text-primary-500' - ) + const result = wrapper.html() + await expect(result).toMatchFileSnapshot('./test/secondary.output.html') + }) + + test('secondary disabled button snapshot', async () => { + createComponent({ props: { color: 'secondary', disabled: true } }) + const result = wrapper.html() + await expect(result).toMatchFileSnapshot('./test/secondary-disabled.output.html') }) - test('text button classes is correct', () => { - createComponent({ props: { color: 'link' } }) - expect(wrapper.classes().join(' ')).toEqual( - 'focus:ring-4 focus:ring-primary-200 font-medium rounded text-sm px-5 py-2.5 mr-2 mb-2 focus:outline-none text-primary-500 bg-transparent hover:bg-primary-100 dark:hover:bg-primary-650 dark:hover:text-primary-400' - ) + test('text button classes is correct', async () => { + createComponent({ props: { color: 'text' } }) + + const result = wrapper.html() + await expect(result).toMatchFileSnapshot('./test/text.output.html') + }) + + test('text button disabled snapshot', async () => { + createComponent({ props: { color: 'text' } }) + + const result = wrapper.html() + await expect(result).toMatchFileSnapshot('./test/text-disabled.output.html') }) }) diff --git a/src/components/BuiButton/BuiButton.story.vue b/src/components/BuiButton/BuiButton.story.vue index 275f91a..01fe3a2 100644 --- a/src/components/BuiButton/BuiButton.story.vue +++ b/src/components/BuiButton/BuiButton.story.vue @@ -1,16 +1,59 @@ + + +# BuiButton + +## Props: + +### color + +Values: `primary` | `secondary` | `text` + +### size + +Values: `lg` | `md` | `sm` + diff --git a/src/components/BuiButton/BuiButton.vue b/src/components/BuiButton/BuiButton.vue index b314733..e8cf7d1 100644 --- a/src/components/BuiButton/BuiButton.vue +++ b/src/components/BuiButton/BuiButton.vue @@ -1,32 +1,91 @@ diff --git a/src/components/BuiButton/test/default-disabled.output.html b/src/components/BuiButton/test/default-disabled.output.html new file mode 100644 index 0000000..d4ac35b --- /dev/null +++ b/src/components/BuiButton/test/default-disabled.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/test/default.output.html b/src/components/BuiButton/test/default.output.html new file mode 100644 index 0000000..0924082 --- /dev/null +++ b/src/components/BuiButton/test/default.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/test/secondaey.output.html b/src/components/BuiButton/test/secondaey.output.html new file mode 100644 index 0000000..23aa750 --- /dev/null +++ b/src/components/BuiButton/test/secondaey.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/test/secondary-disabled.output.html b/src/components/BuiButton/test/secondary-disabled.output.html new file mode 100644 index 0000000..b443ce6 --- /dev/null +++ b/src/components/BuiButton/test/secondary-disabled.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/test/secondary.output.html b/src/components/BuiButton/test/secondary.output.html new file mode 100644 index 0000000..23c33ba --- /dev/null +++ b/src/components/BuiButton/test/secondary.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/test/text-disabled.output.html b/src/components/BuiButton/test/text-disabled.output.html new file mode 100644 index 0000000..aaf9e5a --- /dev/null +++ b/src/components/BuiButton/test/text-disabled.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/test/text.output.html b/src/components/BuiButton/test/text.output.html new file mode 100644 index 0000000..aaf9e5a --- /dev/null +++ b/src/components/BuiButton/test/text.output.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BuiButton/types.ts b/src/components/BuiButton/types.ts index 8836811..8c1edd9 100644 --- a/src/components/BuiButton/types.ts +++ b/src/components/BuiButton/types.ts @@ -1 +1,2 @@ -export type ButtonColor = 'primary' | 'secondary' | 'link' +export type ButtonColor = 'primary' | 'secondary' | 'text' | 'outline' +export type ButtonSize = 'lg' | 'md' | 'sm' diff --git a/src/components/BuiInput/BuiInput.spec.ts b/src/components/BuiInput/BuiInput.spec.ts index 8c6a36b..574e603 100644 --- a/src/components/BuiInput/BuiInput.spec.ts +++ b/src/components/BuiInput/BuiInput.spec.ts @@ -4,17 +4,17 @@ import { describe, expect, test } from 'vitest' import type { TestWrapper } from '../../types/globalTypes' describe('BuiInput', () => { - // @ts-ignore + // @ts-ignore-next-line let wrapper: TestWrapper - const createComponent = (props: any) => { + const createComponent = (props?: any) => { wrapper = shallowMount(BuiInput, { global: { stubs: { teleport: true } }, ...props }) } test('input event fired', async () => { - createComponent({ props: { color: 'primary' } }) + createComponent() const input = wrapper.find('input') await input.setValue('some-text') @@ -24,7 +24,7 @@ describe('BuiInput', () => { }) test('focus event fired', async () => { - createComponent({ props: { color: 'primary' } }) + createComponent() const input = wrapper.find('input') await input.trigger('focus') @@ -33,11 +33,55 @@ describe('BuiInput', () => { }) test('blur event fired', async () => { - createComponent({ props: { color: 'primary' } }) + createComponent() const input = wrapper.find('input') await input.trigger('blur') expect(wrapper.emitted()).toHaveProperty('blur') }) + + test('default classes is correct', async () => { + createComponent() + const input = wrapper.find('input') + expect(input.classes().join(' ')).toEqual( + 'py-2 px-3 border border-slate-300 dark:border-gray-500 dark:focus:border-primary-500 focus:border-primary-500 bg-transparent rounded-lg focus:ring-4 focus:ring-primary-200 dark:focus:ring-primary-550 outline-none w-full dark:text-gray-100 text-clay-500 placeholder-gray-500' + ) + }) + + test('error classes is correct', async () => { + createComponent({ props: { validationStatus: 'error' } }) + const input = wrapper.find('input') + expect(input.classes().join(' ')).toEqual( + 'py-2 px-3 border dark:border-gray-500 dark:focus:border-primary-500 bg-transparent rounded-lg focus:ring-4 dark:focus:ring-primary-550 outline-none w-full dark:text-gray-100 text-clay-500 placeholder-gray-500 border-red-300 focus:border-red-300 focus:ring-red-200' + ) + }) + + test('success classes is correct', async () => { + createComponent({ props: { validationStatus: 'success' } }) + const input = wrapper.find('input') + expect(input.classes().join(' ')).toEqual( + 'py-2 px-3 border dark:border-gray-500 dark:focus:border-primary-500 bg-transparent rounded-lg focus:ring-4 dark:focus:ring-primary-550 outline-none w-full dark:text-gray-100 text-clay-500 placeholder-gray-500 border-green-300 focus:border-green-300 focus:ring-green-200' + ) + }) + + test('hepler slot is rendered', async () => { + createComponent({ + slots: { + helper: 'Helper text' + } + }) + + expect(wrapper.text()).toContain('Helper text') + }) + + test('validation message slot rendered', async () => { + createComponent({ + slots: { + validationMessage: 'Validation message' + } + }) + + expect(wrapper.text()).toContain('Validation message') + }) }) diff --git a/tailwind.config.ts b/tailwind.config.ts index 7fdaf93..394cb88 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -7,12 +7,18 @@ module.exports = { primary: { 100: '#f9f9ff', 150: '#f4f4ff', + 175: '#e8e8ff', 200: '#d2d2fd', + 225: '#babaf4', + 250: '#b1affd', 300: '#adabf9', 400: '#8989ff', 500: '#7371F9', 550: '#5957E8', + 575: '#4e4cca', + 590: '#5151a8', 600: '#413f7c', + 625: '#35345e', 650: '#2f2e51', 700: '#323149', 800: '#292841' @@ -25,7 +31,9 @@ module.exports = { }, gray: { 100: '#F5F6F8', + 150: '#F8F8FA', 200: '#F8F8FA', + 400: '#AAAFBD', 500: '#737680' }, red: {