Skip to content

Latest commit

 

History

History
254 lines (192 loc) · 10.3 KB

File metadata and controls

254 lines (192 loc) · 10.3 KB

Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved.

Following these guidelines helps to get issues organised and PRs merged faster!

Core Ideas

  • Components should work across all platforms (web, iOS, Android) to the same level of minimum functionality (as determined by UX). This is to ensure that master is always in a releasable state and app projects can use our components with confidence. To enable this we're using react-native-web
  • Components should provide a suite of sensible events for their interactions. This will allow metric components to report back for a given context
  • Screenshots are required for visual changes on web, iOS and Android. Pictures are worth a thousand words
  • Only add components that are wanted. They should form part of a larger feature and not be added in isolation because they might be useful in the future
  • Use React perf and Chrome dev tools to identify issues AFTER the code is functionally complete

Convention

  • In general we use yarn, add a yarn.lock file and keep it up to date for faster builds
  • We use flow and Prettier to ensure code consistency and reliability, this pattern should also be followed to avoid typical dev bike-shedding
  • For testing we’re using Jest for unit and integration tests. React Native integration tests will use Detox

Heuristics

We're using lerna for the monorepo with each component in it's own package that should stand alone with it's own tests and react story etc. A component is simply the exported JSX with no compilation

For ease of use there is a CLI for creating a component. Run ./times-components for instructions, this is the quickest way to create a package with the required scaffolding which is; a component, package.json, stubbed test and story. Note that the stubbed test will fail until a snapshot is created with jest --updateSnapshot or a test run is made without the --CI flag

When developing a component it's easiest to use the storybooks with hot reloading. Make sure you follow the React Native instructions to get up and running first. See README.md for commands to run the storybook.

Caution

There are some problems regarding the usage of native storybooks with the Android simulator, mainly with hot module reloading (HMR). To take full advantage of HMR while developing components while testing with storybooks use the iOS simulator instead.

npm run storybook:build will output the built web storybook into the default storybook-static folder that is synced to the gh_pages branch to demo the components in the web

When the CI passes packages:publish will be run that uses conventional commits to bump to the correct semver version, create a CHANGELOG and push to the @times-components org on npm

update-deps is run postinstall to add node_modules to each of the packages

Submitting a Pull Request

Good pull requests, such as patches, improvements, and new features, are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. There should be a single PR for each component/package

Please ask first if somebody else is already working on this or the core developers think your feature is in-scope. Generally always have a related issue with discussions for whatever you are including.

Testing

Every component should have a XXXX.test.js file with the component's Jest tests.

If the component contains functionality that requires functional testing on a device or browser, you can use Fructose. This should follow the naming convention, XXXX.fructose.js.

Fructose uses detox to instrument the tests. In order to run the tests you will need to install some additional dependencies. Follow steps 1-4 in these detox docs.

Fructose also relies on an application existing within the project, in this case we are using the storybook app. If you have not installed it, you can do so by running yarn ios. You will need to terminate the server that is run with this as fructose will run its own at the time of testing. As long as you do not delete the app, you will only have to build the app once.

If you run npm run functional-test:ios in the root directory it will run fructose tests for all of the components. This will similarly work for android and web.

Dextrose is a visual snapshotting tool designed to make the visual inspection of components easier.

In order to run dextrose simply use yarn visual-snapshot-web, yarn visual-snapshot-ios or yarn visual-snapshot-android. Each component that has differences from master will be visually snapshotted and saved under the /dextrose/snappy folder. This can be very useful for visually validating components.

Local App Deployment

Android

Follow these steps to deploy storybook native to a real android device.

  • Plug the device into the computer
  • Make sure your android device has trusted the connected computer and that usb debugging / developer mode has been turned on.
  • For Android <4.2 go to Developer Options => Enable USB Debugging, and for Android >=4.2 go to About Phone/Tablet => Tap Build Number 7 Times => Developer Options => Enable USB Debugging
  • Install android tooling through brew cask install android-platform-tools
  • Optionally start a local instance of The Times Public Api (dependent on the stories you intend to view)
  • Run yarn
  • Run yarn storybook-native
  • Run yarn android:device (to enable Times API)
  • Open storybook native on your computer and load a story

Troublshooting

  • If your device is complaining about about story-loader.js not existing - run yarn storybook-native before yarn android. This should generate the missing file.
  • If your device is complaining about being unable to reach localhost or 404 use the adb commands. Shake the device to bring up the developer menu and reload the app
  • If still struggling; shake the device and debug js remotely. Open a console on your computer for more info on the error
  • If you're still struggling verify that you are able to run yarn storybook and that it works in web view.
  • If you receive a ":CFBundleIdentifier", Does Not Exist error when trying to run yarn ios, try clearing your React Native cache with rm -r ~/.rncache and clearing third part libraries rm -r <your-project>/node_modules/react-native/third_party. This happens when React Native caches third party tools for previous versions of React Native.

Font Naming Conventions

Android and iOS interpret fonts differently. The style property for fontFamily on iOS refers to the internal post script name of the font. The style property for fontFamily on Android refers to the filename of the font. React Native Android only supports 4 font weights, therefore we have made the following conventions

Also the fonts should have the correct weight and style meta attributes

For all fonts which are; regular, bold, italic, bold and italic variants

Filename format (physical file name): <fontname>_<weight> eg

  • TimesDigitalW04.ttf
  • TimesDigitalW04_italic.ttf
  • TimesDigitalW04_bold.ttf

EXCEPT FOR REGULAR eg

TimesDigitalW04.ttf for a TimesDigitalW04-Regular.ttf font

FontName format (meta of the font): <fontname>-<weight> eg

  • TimesDigitalW04-Regular
  • TimesDigitalW04-Italic
  • TimesDigitalW04-Bold

Family Name format (meta of the font): <fontname> eg

  • TimesDigitalW04

For fonts which have a font weight that is outside of the above font weights and styles

The filename, font name and family name should refer to the complete font file name

  • Filename format: <fontname>-<weight>
  • Font Name / Full name format : <fontname>-<weight>
  • Family Name format: <fontname>-<weight>

eg

  • Filename = GillSansMTStd-Medium
  • FontName / Full name = GillSansMTStd-Medium
  • FamilyName = GillSansMTStd-Medium

Folder Structure

An example component/package looks like this:

.
└── card
    ├── CHANGELOG.md
    ├── __snapshots__
    │   └── card.test.js.snap
    ├── card.js
    ├── card.stories.js
    ├── card.test.js
    ├── package.json
    └── yarn.lock

Overview of project directory structure

  • .storybook houses the web storybook config that dynamically loads the component stories and aliases the native imports to web
  • .storybook.native is home to the generated story-loader.js from the prestorybook-native npm script, and the storybook bootstrapping
  • android, ios, .babelrc, .buckconfig, .flowconfig, .gitattributes, .watchmanconfig, app.json are all from a stock react-native project in order to run the native storybook
  • lerna.json specifies that the packages are independent so different platforms can control which versions they consume and allows them to develop organically

Setting Up a Local Copy

  1. Clone the repo with https://github.com/newsuk/times-components.git

  2. Run yarn in the root folder.

Once it is done, you can run npm run storybook and/or npm run storybook-native

Provider package

The Provider package is home to any GraphQL queries that should be shared across the various platforms. The Times Public API schema is checked in as schema.json which should be updated when any fields are changed. The packages linting will then check that each of the gql queries within the package are properly formed

Cutting a Release

Each component should be bumped and published correctly when it is merged to master and has passed the CI process

This was heavily sourced from CRA