diff --git a/.circleci/config.yml b/.circleci/config.yml index ec583bfe6d..f99e877a82 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,9 +11,9 @@ jobs: - restore_cache: keys: # Restore cached node_modules - - v1-dependencies-{{ checksum "yarn.lock" }} + - v3-dependencies-{{ checksum "yarn.lock" }} # fallback to using the latest cache if no exact match is found - - v1-dependencies- + - v3-dependencies- - run: name: Add CI global modules @@ -43,7 +43,7 @@ jobs: - save_cache: paths: - node_modules - key: v1-dependencies-{{ checksum "yarn.lock" }} + key: v3-dependencies-{{ checksum "yarn.lock" }} validate: docker: - image: circleci/node:8.11.3-browsers @@ -53,7 +53,7 @@ jobs: - restore_cache: keys: - - v1-dependencies-{{ checksum "yarn.lock" }} + - v3-dependencies-{{ checksum "yarn.lock" }} - run: # PR's from forks cannot use the dependency cache for performance reasons @@ -63,7 +63,7 @@ jobs: - run: name: Lint + Typecheck command: yarn validate - test: + test-unit: docker: - image: circleci/node:8.11.3-browsers working_directory: ~/repo @@ -72,7 +72,7 @@ jobs: - restore_cache: keys: - - v1-dependencies-{{ checksum "yarn.lock" }} + - v3-dependencies-{{ checksum "yarn.lock" }} - run: # PR's from forks cannot use the dependency cache for performance reasons @@ -87,18 +87,7 @@ jobs: - store_test_results: path: test-reports/junit - - - run: - name: Browser Suite - command: node browser-test-harness.js yarn test:browser - - - store_test_results: - path: test-reports/browser - - - store_artifacts: - path: .storybook-out - destination: storybook-out - bundle-test: + test-bundle: docker: - image: circleci/node:8.11.3-browsers working_directory: ~/repo @@ -107,17 +96,43 @@ jobs: - restore_cache: keys: - - v1-dependencies-{{ checksum "yarn.lock" }} + - v3-dependencies-{{ checksum "yarn.lock" }} + # PR's from forks cannot use the dependency cache for performance reasons - run: - # PR's from forks cannot use the dependency cache for performance reasons name: 'Forked PR dependency install' command: yarn - run: name: Check Bundle Size command: yarn run bundle-size:check + test-browser: + docker: + # Single Docker container with Node 8 and Cypress dependencies + # https://github.com/cypress-io/circleci-orb/blob/master/src/orb.yml + - image: cypress/base:8 + working_directory: ~/repo + steps: + - checkout + + - restore_cache: + keys: + - v3-dependencies-{{ checksum "yarn.lock" }} + + # PR's from forks cannot use the dependency cache for performance reasons + - run: + name: 'Forked PR dependency install' + command: yarn + - run: + name: 'Run cypress' + command: node browser-test-harness.js yarn test:browser:ci + + # store videos and screenshots (if any) as CI artifacts + - store_artifacts: + path: cypress/videos + - store_artifacts: + path: cypress/screenshots workflows: version: 2 build: @@ -126,9 +141,12 @@ workflows: - validate: requires: - install - - test: + - test-unit: + requires: + - install + - test-bundle: requires: - install - - bundle-test: + - test-browser: requires: - install diff --git a/.eslintignore b/.eslintignore index 278e582071..8004ac6e73 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,4 +2,5 @@ dist/ flow-typed/ site/ +coverage/ babel.config.js diff --git a/.eslintrc.js b/.eslintrc.js index c9c7acdd50..57eb2b1271 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,7 @@ module.exports = { 'plugin:prettier/recommended', ], parser: 'babel-eslint', - plugins: ['prettier', 'flowtype', 'react', 'import', 'jest'], + plugins: ['prettier', 'flowtype', 'emotion', 'react', 'import', 'jest'], env: { es6: true, browser: true, diff --git a/.flowconfig b/.flowconfig index da32d74e10..43eb1b40c9 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,4 +1,9 @@ -[ignore] +[untyped] +# Issue with atlaskit/theme typing +.*/node_modules/@atlaskit/theme + +[libs] +./flow-typed/custom/ [options] diff --git a/.gitignore b/.gitignore index b8baa60a64..6761f35121 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,9 @@ coverage/ # test reports test-reports/ +# test videos +cypress/videos/ + # storybook .storybook.out .cache/ diff --git a/.size-snapshot.json b/.size-snapshot.json index 9ff8c3b6fb..ec67a8043a 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -1,25 +1,25 @@ { "dist/react-beautiful-dnd.js": { - "bundled": 347275, - "minified": 134225, - "gzipped": 39798 + "bundled": 355996, + "minified": 138322, + "gzipped": 40545 }, "dist/react-beautiful-dnd.min.js": { - "bundled": 295057, - "minified": 109593, - "gzipped": 31944 + "bundled": 302438, + "minified": 113232, + "gzipped": 32713 }, "dist/react-beautiful-dnd.esm.js": { - "bundled": 228983, - "minified": 120746, - "gzipped": 30051, + "bundled": 236773, + "minified": 125151, + "gzipped": 31183, "treeshaked": { "rollup": { - "code": 81922, - "import_statements": 846 + "code": 85436, + "import_statements": 832 }, "webpack": { - "code": 84599 + "code": 88124 } } } diff --git a/.storybook-out b/.storybook-out deleted file mode 100644 index c35ffcccf2..0000000000 --- a/.storybook-out +++ /dev/null @@ -1,3 +0,0 @@ -yarn run v1.2.1 -$ start-storybook -p 9002 & opn http://localhost:9002 -Done in 0.35s. diff --git a/.storybook/addons.js b/.storybook/addons.js deleted file mode 100644 index 8b4d35d73e..0000000000 --- a/.storybook/addons.js +++ /dev/null @@ -1 +0,0 @@ -import '@storybook/addon-options/register'; diff --git a/.storybook/compressed-logo-rbd.svg b/.storybook/compressed-logo-rbd.svg new file mode 100644 index 0000000000..3e295c61d0 --- /dev/null +++ b/.storybook/compressed-logo-rbd.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.storybook/config.js b/.storybook/config.js index ac51458216..83bb3686ed 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -1,20 +1,29 @@ import React from 'react'; -import { configure, addDecorator } from '@storybook/react'; -import { withOptions } from '@storybook/addon-options'; -import PopIframeDecorator from './decorator/pop-iframe'; +import { addParameters, configure, addDecorator } from '@storybook/react'; +import { create } from '@storybook/theming'; +import GlobalStylesDecorator from './decorator/global-styles'; // adding css reset - storybook includes a css loader import '@atlaskit/css-reset'; +import { colors } from '@atlaskit/theme'; +import logo from './compressed-logo-rbd.svg'; import { version } from '../package.json'; -addDecorator( - withOptions({ - name: 'react-beautiful-dnd', - url: 'https://github.com/atlassian/react-beautiful-dnd', - showAddonPanel: false, - }), -); +const theme = create({ + brandImage: logo, + brandName: 'react-beautiful-dnd', + brandUrl: 'https://github.com/atlassian/react-beautiful-dnd', +}); -addDecorator(PopIframeDecorator); +addParameters({ + options: { + // currently not using any addons + showPanel: false, + theme, + }, +}); + +// Using theme would be good for this, but it looks like theme is just for the chrome around the story +addDecorator(GlobalStylesDecorator); // automatically import all files ending in *.stories.js const req = require.context('../stories/', true, /.stories.js$/); diff --git a/.storybook/decorator/global-styles.jsx b/.storybook/decorator/global-styles.jsx new file mode 100644 index 0000000000..2f3a661320 --- /dev/null +++ b/.storybook/decorator/global-styles.jsx @@ -0,0 +1,17 @@ +// @flow +import React from 'react'; +import styled from '@emotion/styled'; +import { colors } from '@atlaskit/theme'; +import { grid } from '../../stories/src/constants'; + +const GlobalStyles = styled.div` + background-color: ${colors.N0}; + min-height: 100vh; + color: ${colors.N900}; +`; + +const GlobalStylesDecorator = (storyFn: Function) => ( + {storyFn()} +); + +export default GlobalStylesDecorator; diff --git a/.storybook/decorator/pop-iframe.jsx b/.storybook/decorator/pop-iframe.jsx deleted file mode 100644 index fc03cddfc8..0000000000 --- a/.storybook/decorator/pop-iframe.jsx +++ /dev/null @@ -1,142 +0,0 @@ -// @flow -import React, { type Node } from 'react'; -import styled from 'styled-components'; - -type Props = { - children: Node, -}; - -const ButtonBox = styled.div` - display: flex; - position: fixed; - left: 0; - bottom: 0; - margin: 8px; -`; - -const Button = styled.button` - padding: 8px; - font-size: 16px; - - :hover { - cursor: pointer; - } -`; - -const isSSR: boolean = typeof window === 'undefined'; - -const canPopOutOfIframe: boolean = (() => { - if (isSSR) { - return false; - } - try { - // this can violate a same origin policy if on a different domain - return window.self !== window.top; - } catch (e) { - // cannot pop out as it would violate the same origin policy - return false; - } -})(); - -const canPopIntoIframe: boolean = (() => { - if (isSSR || canPopOutOfIframe) { - return false; - } - // already the top level - try { - return window.self === window.top; - } catch (e) { - // would have been in an iframe that we cannot leave - this codepath should never be hit - return false; - } -})(); - -const canPop: boolean = canPopIntoIframe || canPopOutOfIframe; - -type State = {| - isLoading: boolean, - isHidden: boolean, -|}; - -class PopIframe extends React.Component { - state: State = { - isLoading: false, - isHidden: false, - }; - - getButton = (): ?Node => { - if (this.state.isHidden) { - return null; - } - - if (!canPop) { - return null; - } - - const action: Node = canPopOutOfIframe ? ( -