diff --git a/cypress/integration/responsive-props/behavior-down.test.js b/cypress/integration/responsive-props/behavior-down.test.js new file mode 100644 index 00000000..de12c526 --- /dev/null +++ b/cypress/integration/responsive-props/behavior-down.test.js @@ -0,0 +1,31 @@ +describe('Behavior: "down"', () => { + before(() => { + cy.loadStory(['core'], ['responsive-props', 'compound']) + }) + + it('with multiple "down" props', () => { + const assertPadding = (values) => { + return cy.get('#composition-down').should('have.css', 'padding', values) + } + + assertPadding('10px') + cy.setBreakpoint('sm').then(() => assertPadding('20px')) + cy.setBreakpoint('md').then(() => assertPadding('30px')) + cy.setBreakpoint('lg').then(() => assertPadding('40px')) + cy.setBreakpoint('xl').then(() => assertPadding('50px')) + }) + + it('when combined with "up" sibling', () => { + const assertTemplateCols = (value) => { + return cy + .get('#composition-combination') + .should('have.css', 'grid-template-columns', value) + } + + assertTemplateCols('200px') + cy.setBreakpoint('sm').then(() => assertTemplateCols('100px')) + cy.setBreakpoint('md').then(() => assertTemplateCols('200px')) + cy.setBreakpoint('lg').then(() => assertTemplateCols('200px')) + cy.setBreakpoint('xl').then(() => assertTemplateCols('200px')) + }) +}) diff --git a/cypress/integration/responsive-props/index.js b/cypress/integration/responsive-props/index.js index c800d828..dad90ea2 100644 --- a/cypress/integration/responsive-props/index.js +++ b/cypress/integration/responsive-props/index.js @@ -2,4 +2,5 @@ describe('Responsive props', () => { require('./mobile-first.test') require('./breakpoint-specific.test') require('./inclusive-notch.test') + require('./behavior-down.test') }) diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 2c9a60aa..910fb016 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -43,7 +43,5 @@ module.exports = (on, config) => { ) const { envName } = config.env - const env = getCypressConfig(envName) - console.log({ env }) - return env + return getCypressConfig(envName) } diff --git a/example.png b/example.png deleted file mode 100644 index 2719d194..00000000 Binary files a/example.png and /dev/null differ diff --git a/examples/Core/ResponsiveProps/BreakpointSpecific.jsx b/examples/Core/ResponsiveProps/BreakpointSpecific.jsx index 4a0fdda5..fde77191 100644 --- a/examples/Core/ResponsiveProps/BreakpointSpecific.jsx +++ b/examples/Core/ResponsiveProps/BreakpointSpecific.jsx @@ -1,10 +1,7 @@ import React from 'react' -import Layout, { Composition } from 'atomic-layout' -// import resetLayout from '../resetLayout' +import { Composition } from 'atomic-layout' import Square from '@stories/Square' -// resetLayout(Layout) - const BreakpointSpecific = () => ( ( + <> + {/* Multiple "down" behaviors */} + + First + + + {/* Combination of "up" and "down" */} + + First + Second + + +) + +export default CompoundResponsiveProps diff --git a/examples/Core/ResponsiveProps/InclusiveNotch.jsx b/examples/Core/ResponsiveProps/InclusiveNotch.jsx index d1a8b351..493013a8 100644 --- a/examples/Core/ResponsiveProps/InclusiveNotch.jsx +++ b/examples/Core/ResponsiveProps/InclusiveNotch.jsx @@ -1,10 +1,7 @@ import React from 'react' -import Layout, { Composition } from 'atomic-layout' -// import resetLayout from '../resetLayout' +import { Composition } from 'atomic-layout' import Square from '@stories/Square' -// resetLayout(Layout) - const template = 'first second' const InclusiveNotch = () => ( diff --git a/examples/Core/ResponsiveProps/MobileFirst.jsx b/examples/Core/ResponsiveProps/MobileFirst.jsx index 12834907..0b55e1ed 100644 --- a/examples/Core/ResponsiveProps/MobileFirst.jsx +++ b/examples/Core/ResponsiveProps/MobileFirst.jsx @@ -1,10 +1,7 @@ import React from 'react' -import Layout, { Composition } from 'atomic-layout' -// import resetLayout from '../resetLayout' +import { Composition } from 'atomic-layout' import Square from '@stories/Square' -// resetLayout(Layout) - const Foo = () => ( {({ First, Second }) => ( diff --git a/examples/index.js b/examples/index.js index 56411eba..76855bd7 100644 --- a/examples/index.js +++ b/examples/index.js @@ -22,11 +22,13 @@ storiesOf('Core|Rendering', module) import MobileFirstResponsiveProps from './Core/ResponsiveProps/MobileFirst' import BreakpointSpecificResponsiveProps from './Core/ResponsiveProps/BreakpointSpecific' import InclusiveNotchResponsiveProps from './Core/ResponsiveProps/InclusiveNotch' +import CompoundResponsiveProps from './Core/ResponsiveProps/Compound' storiesOf('Core|Responsive props', module) .add('Mobile-first', () => ) .add('Breakpoint-specific', () => ) .add('Inclusive-notch', () => ) + .add('Compound', () => ) /** * Configuration diff --git a/package.json b/package.json index 564dceb3..1d272a43 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,10 @@ "name": "atomic-layout", "version": "0.7.1", "description": "A single component to distribute a spacial relation in your layouts using CSS Grid.", + "author": { + "name": "Artem Zakharchenko", + "email": "kettanaito@gmail.com" + }, "main": "lib/index.js", "types": "lib/types/index.d.ts", "scripts": { @@ -23,7 +27,7 @@ }, "lint-staged": { "*.{ts,tsx}": [ - "eslint ./src/", + "tslint ./src/", "prettier --write", "git add" ] @@ -34,10 +38,6 @@ "maxSize": "20 kB" } ], - "author": { - "name": "Artem Zakharchenko", - "email": "kettanaito@gmail.com" - }, "repository": { "type": "git", "url": "https://github.com/kettanaito/atomic-layout" diff --git a/src/utils/breakpoints/getAreaBreakpoints/getAreaBreakpoints.spec.ts b/src/utils/breakpoints/getAreaBreakpoints/getAreaBreakpoints.spec.ts index 3d6aba40..f5ea0f7f 100644 --- a/src/utils/breakpoints/getAreaBreakpoints/getAreaBreakpoints.spec.ts +++ b/src/utils/breakpoints/getAreaBreakpoints/getAreaBreakpoints.spec.ts @@ -68,7 +68,7 @@ test('Notch', () => { ]) }) -describe('Shuffled behavior', () => { +describe('Combined behavior', () => { test('Concatenates sibling areas with "down" behavior', () => { const breakpointSm = Layout.getBreakpoint('sm') || {} const breakpointMd = Layout.getBreakpoint('md') || {} diff --git a/src/utils/invariant/invariant.spec.ts b/src/utils/invariant/invariant.spec.ts index cd4a7697..7e6009a7 100644 --- a/src/utils/invariant/invariant.spec.ts +++ b/src/utils/invariant/invariant.spec.ts @@ -2,7 +2,7 @@ import invariant from './invariant' const createConsoleSpy = () => jest.spyOn(console, 'error') -test('Should error when predicate is not satisfied', () => { +test('Errors upon not satisfied predicate', () => { const consoleError = createConsoleSpy() const errorMessage = 'Error message' @@ -12,7 +12,7 @@ test('Should error when predicate is not satisfied', () => { consoleError.mockRestore() }) -test('Should do nothing when predicate is satisfied', () => { +test('Does nothing upon satisfied predicate', () => { const consoleError = createConsoleSpy() invariant(true, 'You should not see this') diff --git a/src/utils/strings/capitalize/capitalize.spec.ts b/src/utils/strings/capitalize/capitalize.spec.ts index 3c405a6b..4d5b1b76 100644 --- a/src/utils/strings/capitalize/capitalize.spec.ts +++ b/src/utils/strings/capitalize/capitalize.spec.ts @@ -4,3 +4,8 @@ test('Capitalizes the given string', () => { expect(capitalize('foo')).toBe('Foo') expect(capitalize('fooSome')).toBe('FooSome') }) + +test('Returns already capitalized string as-is', () => { + expect(capitalize('Foo')).toBe('Foo') + expect(capitalize('FooSome')).toBe('FooSome') +}) diff --git a/src/utils/strings/getPrefix/getPrefix.spec.ts b/src/utils/strings/getPrefix/getPrefix.spec.ts index 8f23520b..e328e7dd 100644 --- a/src/utils/strings/getPrefix/getPrefix.spec.ts +++ b/src/utils/strings/getPrefix/getPrefix.spec.ts @@ -1,6 +1,6 @@ import getPrefix from './getPrefix' -test('Returns the min/max prefix of the given string', () => { +test('Returns min/max prefix of the given string', () => { expect(getPrefix('maxHeight')).toEqual('max') expect(getPrefix('minResolution')).toEqual('min') }) diff --git a/src/utils/strings/hashString/hasString.spec.ts b/src/utils/strings/hashString/hasString.spec.ts index f5623bf1..2fa5f6bb 100644 --- a/src/utils/strings/hashString/hasString.spec.ts +++ b/src/utils/strings/hashString/hasString.spec.ts @@ -1,13 +1,13 @@ import hashString from './hashString' test('Returns numeric hash based on the given string', () => { - const str = 'template:header,content,footer' - expect(hashString(str)).toEqual(1927731245) - expect(hashString(str)).toEqual(1927731245) + const templateString = 'template:header,content,footer' + expect(hashString(templateString)).toEqual(1927731245) + expect(hashString(templateString)).toEqual(1927731245) expect(hashString('templateMd:header,content,footer')).toEqual(1323128868) }) -test('Returns zero for an empty string', () => { +test('Returns zero for empty string', () => { expect(hashString('')).toEqual(0) }) diff --git a/src/utils/strings/parsePropName/parsePropName.spec.ts b/src/utils/strings/parsePropName/parsePropName.spec.ts index e1b7dd9d..89b65a60 100644 --- a/src/utils/strings/parsePropName/parsePropName.spec.ts +++ b/src/utils/strings/parsePropName/parsePropName.spec.ts @@ -1,77 +1,79 @@ import Layout from '../../../Layout' import parsePropName from './parsePropName' -test('Parses a prop name without breakpoint or behavior', () => { - expect(parsePropName('gutter')).toEqual({ - originPropName: 'gutter', - purePropName: 'gutter', - behavior: 'up', - breakpoint: { - name: 'xs', - isDefault: true, - }, +describe('Parses a prop name', () => { + test('without breakpoint or behavior', () => { + expect(parsePropName('gutter')).toEqual({ + originPropName: 'gutter', + purePropName: 'gutter', + behavior: 'up', + breakpoint: { + name: 'xs', + isDefault: true, + }, + }) }) -}) -test('Parses a prop name with breakpoint without behavior', () => { - expect(parsePropName('gutterMd')).toEqual({ - originPropName: 'gutterMd', - purePropName: 'gutter', - behavior: 'up', - breakpoint: { - name: 'md', - isDefault: false, - }, + test('with breakpoint, without behavior', () => { + expect(parsePropName('gutterMd')).toEqual({ + originPropName: 'gutterMd', + purePropName: 'gutter', + behavior: 'up', + breakpoint: { + name: 'md', + isDefault: false, + }, + }) }) -}) -test('Parses prop name with behavior and without breakpoint', () => { - expect(parsePropName('gutterDown')).toEqual({ - originPropName: 'gutterDown', - purePropName: 'gutter', - behavior: 'down', - breakpoint: { - name: 'xs', - isDefault: true, - }, + test('with behavior and without breakpoint', () => { + expect(parsePropName('gutterDown')).toEqual({ + originPropName: 'gutterDown', + purePropName: 'gutter', + behavior: 'down', + breakpoint: { + name: 'xs', + isDefault: true, + }, + }) }) -}) -test('Parses a prop name with a breakpoint and behavior', () => { - expect(parsePropName('gutterLgOnly')).toEqual({ - originPropName: 'gutterLgOnly', - purePropName: 'gutter', - behavior: 'only', - breakpoint: { - name: 'lg', - isDefault: false, - }, - }) + test('with breakpoint and behavior', () => { + expect(parsePropName('gutterLgOnly')).toEqual({ + originPropName: 'gutterLgOnly', + purePropName: 'gutter', + behavior: 'only', + breakpoint: { + name: 'lg', + isDefault: false, + }, + }) - expect(parsePropName('paddingVerticalMdDown')).toEqual({ - originPropName: 'paddingVerticalMdDown', - purePropName: 'paddingVertical', - behavior: 'down', - breakpoint: { - name: 'md', - isDefault: false, - }, + expect(parsePropName('paddingVerticalMdDown')).toEqual({ + originPropName: 'paddingVerticalMdDown', + purePropName: 'paddingVertical', + behavior: 'down', + breakpoint: { + name: 'md', + isDefault: false, + }, + }) }) -}) -test('Ignores unknown suffixes', () => { - expect(parsePropName('gutterFoo')).toEqual({ - originPropName: 'gutterFoo', - purePropName: 'gutterFoo', - behavior: 'up', - breakpoint: { - name: 'xs', - isDefault: true, - }, + test('Ignores unknown suffixes', () => { + expect(parsePropName('gutterFoo')).toEqual({ + originPropName: 'gutterFoo', + purePropName: 'gutterFoo', + behavior: 'up', + breakpoint: { + name: 'xs', + isDefault: true, + }, + }) }) }) -describe('Custom layout breakpoints', () => { +describe('Parses prop name with custom layout breakpoints', () => { beforeAll(() => { Layout.configure({ defaultBreakpointName: 'mobile', @@ -83,7 +85,7 @@ describe('Custom layout breakpoints', () => { }) }) - test('Parses a prop name without breakpoint or behavior', () => { + test('without breakpoint or behavior', () => { expect(parsePropName('marginLeft')).toEqual({ originPropName: 'marginLeft', purePropName: 'marginLeft', @@ -95,7 +97,7 @@ describe('Custom layout breakpoints', () => { }) }) - test('Parses a prop name with custom breakpoint and without behavior', () => { + test('with custom breakpoint and without behavior', () => { expect(parsePropName('templateTablet')).toEqual({ originPropName: 'templateTablet', purePropName: 'template', @@ -117,7 +119,7 @@ describe('Custom layout breakpoints', () => { }) }) - test('Parses a prop name with behavior without breakpoint', () => { + test('with behavior without breakpoint', () => { expect(parsePropName('templateOnly')).toEqual({ originPropName: 'templateOnly', purePropName: 'template', @@ -129,7 +131,7 @@ describe('Custom layout breakpoints', () => { }) }) - test('Parses a prop name with custom breakpoint and behavior', () => { + test('with custom breakpoint and behavior', () => { expect(parsePropName('paddingHorizontalDesktopRetinaDown')).toEqual({ originPropName: 'paddingHorizontalDesktopRetinaDown', purePropName: 'paddingHorizontal', @@ -141,7 +143,7 @@ describe('Custom layout breakpoints', () => { }) }) - test('Ignores unknown suffixes', () => { + test('ignores unknown suffixes', () => { expect(parsePropName('gutterFoo')).toEqual({ originPropName: 'gutterFoo', purePropName: 'gutterFoo', diff --git a/src/utils/strings/sanitizeTemplateString/sanitizeTemplateString.spec.ts b/src/utils/strings/sanitizeTemplateString/sanitizeTemplateString.spec.ts index d7b43b21..01d3672b 100644 --- a/src/utils/strings/sanitizeTemplateString/sanitizeTemplateString.spec.ts +++ b/src/utils/strings/sanitizeTemplateString/sanitizeTemplateString.spec.ts @@ -1,33 +1,46 @@ import sanitizeTemplateString from './sanitizeTemplateString' -test('Sanitizes a template string with quotes', () => { - const template = ` - 'header header' - 'content aside' - 'footer footer' - ` - - const sanitized = sanitizeTemplateString(template) - expect(sanitized).toEqual(['aside', 'content', 'footer', 'header']) -}) +describe('Sanitizes a given template string', () => { + test('with wrapping quotes', () => { + const template = ` + 'header header' + 'content aside' + 'footer footer' + ` -test('Sanitizes template string without quotes', () => { - const template = ` - first first - second third - fourth fourth - ` + const sanitized = sanitizeTemplateString(template) + expect(sanitized).toEqual(['aside', 'content', 'footer', 'header']) + }) - const sanitized = sanitizeTemplateString(template) - expect(sanitized).toEqual(['first', 'fourth', 'second', 'third']) -}) + test('without wrapping quotes', () => { + const template = ` + first first + second third + fourth fourth + ` + + const sanitized = sanitizeTemplateString(template) + expect(sanitized).toEqual(['first', 'fourth', 'second', 'third']) + }) + + test('with different indentation', () => { + const template = ` + first + second + third + ` + + const sanitized = sanitizeTemplateString(template) + expect(sanitized).toEqual(['first', 'second', 'third']) + }) -test('Sanitizes a template string without indentation', () => { - const template = ` + test('without indentation', () => { + const template = ` first first second third - ` + ` - const sanitized = sanitizeTemplateString(template) - expect(sanitized).toEqual(['first', 'second', 'third']) + const sanitized = sanitizeTemplateString(template) + expect(sanitized).toEqual(['first', 'second', 'third']) + }) }) diff --git a/tests/ssr.spec.tsx b/tests/ssr.spec.tsx index e5f28880..fa554c34 100644 --- a/tests/ssr.spec.tsx +++ b/tests/ssr.spec.tsx @@ -5,22 +5,28 @@ import React from 'react' import { renderToString } from 'react-dom/server' import { Box, Only, Composition } from '../src' -test('Renders server-side without crashing', () => { - const renderOnServer = () => - renderToString( -
- - Responsive content - - {({ First, Second }) => ( - <> - First - Second - - )} - -
, - ) +describe('Server-side rendering', () => { + test('renders without crashing', () => { + const renderOnServer = () => + renderToString( +
+ + Responsive content + + {({ First, Second }) => ( + <> + First + Second + + )} + +
, + ) - expect(renderOnServer).not.toThrow() + expect(renderOnServer).not.toThrow() + }) + + /** + * @todo Include generated HTML string assertions? + */ }) diff --git a/tslint.json b/tslint.json index b21c70fd..d2bbb4db 100644 --- a/tslint.json +++ b/tslint.json @@ -9,10 +9,9 @@ "object-literal-sort-keys": [false, "never"], "only-arrow-functions": [false], "interface-name": [true, "never-prefix"], - "no-submodule-imports": [true, "@src", "@components", "@const", "@utils"], - "no-implicit-dependencies": [ - true, - ["@src", "@components", "@const", "@utils"] - ] + "no-submodule-imports": false, + "no-implicit-dependencies": false, + + "jsx-boolean-value": false } }