Skip to content

StarNeit/AllThings

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

app Build status Renovate enabled styled with prettier JavaScript Style Guide

The ALLTHINGS app — based on react.js.

Content

Prerequisite

NodeJS

As specified in the package.json file, the node engine must be >= 6.5.0 and the npm version must be >=3.0.0.

The best way to manage multiple active NodeJS versions is to use nvm. Please refer to its documentation.

⚠️ Note

"resolutions" in package.json

"resolutions": {
  "uglifyjs-webpack-plugin/uglify-es": "3.1.6"
}

We needed to pin the package uglify-es to a specific version because of a bug that occured. See: https://github.com/allthings/app/pull/1087 This needs to be revisited soon, to make sure we can get rid of this again.

Setup

yarn

Linux user don't need fsevents and should run the following command:

yarn --ignore-optional

Get it running

Create a build

yarn build

This will build 3 bundles:

  • Server side build
  • Client vendor build (react, redux, glamor, etc. see webpack/dll/dll.base.config.js)
  • Client side build (with webpack)

Server side code will land into dist folder and client side code into public/static/js.

Create incremental builds

yarn start

This will watch the file system for change inside the src folder and trigger an incremental build.

After it was rebuilt the node container will be restarted so that the server side can serve the correct bundle.

Important: Webpack DLL is not run in an incremental build. This has to be done either manually by npm run webpack:dll or a full build npm run build.

If everything worked you can go to https://app.dev.allthings.me and see the app running.

If you are targeting the legacy bundle - by default only the modern one is built - append the legacy keyword:

yarn start legacy

Reports

If you want to deep dive into the content of the bundles in order to optimize them, set the following environment variable before performing a yarn build:

export WEBPACK_REPORT=1

The reports will be generated and opened automatically.

To disable it run:

unset WEBPACK_REPORT

Running in standalone development environment

APP_DOMAIN="<your allthings app domain>" \
  OAUTH_CLIENT_ID="<your oauth client id here>" \
  yarn start:standalone

Then navigate to https://app.localhost/

Note: Since the standalone environment uses a self-signed SSL certificate, the first time running the standalone development environment you'll need to confirm an exception to the SSL certificate in your browser. Do this by opening the following two URLs in your browser:

open https://app.localhost/
open https://app-cdn.localhost/

Note 2: Your OAuth client must be valid in the Target API Environment and must be a "public" Client with Authorization Code grant allowed. If it's not a trusted Client, it also needs DPA and TOS fields filled for the User Authorization Screen.

Note 3: The App Domain must exist in the Target API Environment

Note 4: If the localhost subdomains don't resolve, you might try adding the following to your /etc/hosts file.

127.0.0.1	app.localhost
127.0.0.1	app-cdn.localhost
127.0.0.1	app.staging.localhost
127.0.0.1	app.prerelease-magenta.localhost

Choosing a Target API Environment

One can point the App at different environments by using different hostnames:

API Environment URL
Production https://app.localhost/
Staging https://app.staging.localhost/
Prerelease https://app.prerelease-magenta.localhost/

Overview

src/

  • components are not connected to the store and only serve presentational purpose
  • containers should connect to the store and render components passing data
  • microapps are accessible to logged in users and represent a self-contained unit with a menu item and own color theme, e.g. Settings
  • pages are located directly under the root node and are independent of any other part of the app. they can however be wrapped by containers if they need to be connected to the store
  • server is responsible for the server-side rendering of the app
  • store comprises actions, reducers and the store config
  • utils act like internal libraries and offer functions that are used throughout different parts of the app

The basic workflow in this app is powered by redux, which basically consists of a store, actions and reducers.

Store

Nothing too fancy, holds the state of the app.

Actions

To create one or multiple actions use createActions. Should be placed in src/actions

Synchronous actions

const actions = createActions({
  simpleAction (foo, bar) {
    return { payload: { foo, bar } }
  }
  // ...
})

When called, this action will be dispatched automatically with the associated type (given by its name):

actions.simpleAction('Hello', 'World')

/*
This is what the dispatched object looks like:
{
  type: 'simpleAction',
  foo: 'Hello',
  bar: 'World'
}
*/

Asynchronous actions

An async action is recognized by returning a callback instead of an object.

Params given into the callback

Param Type Description
dispatch function Dispatches actions.
api object A function to call the API (provided by the js-sdk)
state function The current application state.
const actions = createActions({
  asyncLogin (user, pass) {
    return async (dispatch, api, state) => {
      dispatch({ status: 'pending' })

      const response = await api({
        path: 'api/some/endpoint',
        params: {
          foo: state.bar
        }
      })
      if (response.status.code === 200) {
        dispatch({ status: 'ok', payload: response.entity })
      } else {
        // Example for an error
        dispatch({ status: 'error', payload: response.error })
      }
    }
  }
})

Reducers

const reducers = createReducers({
  simpleAction (state, action) {
    return {
      ...state,

    }
  },
  asyncLogin (state, action) {
    // action.status one of 'pending', 'ok' or 'error'
  }

})

Developer notes

Tests

Linting

yarn lint

Writing unit tests

Whenever you create or edit a React component or any other JavaScript file, you must update or create a corresponding test file in the same directory.

By convention the test file should be named after the file's name with an additional .test. part:

SomeDir
  | - MyButton.jsx
  | - MyButton.test.jsx
SomeOtherDir
  | - utils.js
  | - utils.test.js

To manually trigger the unit tests, run:

yarn test:unit

You can also use the corresponding watch task:

yarn watch:test:unit

The unit tests are performed using the Jest platform, please refer its documentation.

React component testing is based on the Enzyme testing utility, please refer to its documentation.

The use of snapshots generated by the toMatchSnapshot() method is strongly encouraged. Those snapshots must be always commited as they are a very useful tool whenever you want to make sure your UI does not change unexpectedly

e2e

wdio setup

This is the default and preferred way of writting / running e2e tests. Whenever you have to refactor or create new specs, please use the new setup!

The exhaustive documentation can be found in the e2e repository.

Writting specs

K.I.S.S. principle is the golden rule here 📜.

A spec:

  • should not be any longer than 100 loc, if not split it!
  • should be purely declarative, easy to read. Do not introduce complex utility functions for the sake of making it cleaver, it should be easy to understand!
  • should be testing one piece of functionality, not a complete section (e.g. create / edit / delete).
  • should not test the back-end. The back-end has its own set of unit tests.
  • should not rely on data you have created or modify in another spec. If you expect something to be there, you probably need the db-data dump to be adjusted to your need.

The specs are living in ./test/wdio/test/app/specs/.

The specs are using webdriver i/o, please refer to its own documentation.

Running a spec against your dev environment

You can either use chrome or firefox directly without any additional setup (more browsers / devices are available, please check the e2e repository):

# Run all the specs against chrome and firefox.
yarn wdio
# Run one spec against chrome.
yarn wdio:chrome --spec custom-filter-creation
# Run one spec against firefox.
yarn wdio:firefox --spec custom-filter-creation
Troubleshoot

Getting Cannot start service geckodriver / Cannot start service chromedriver?

cd ./test/wdio && docker-compose down -v

Legacy setup

Writing e2e tests

The e2e tests are written with Nightwatch.js. New tests can be simply added by creating new spec files in the test/e2e/specs directory.

In order to wait for an element before performing any kind of interaction (e.g. a click), you should use the following custom command:

browser
  .waitForElementClickable(someElement)
  .click(someElement)

Please note that the tests are clustered in four different directories (test/specs/app/pipeline-1, test/specs/app/pipeline-2, test/specs/app/pipeline-3, test/specs/app/pipeline-4) in order to get them running concurrently in the CI! They are organized in a way that the average execution time of each folder is almost similar.

Running e2e tests
Run e2e tests in an isolated docker environment
yarn e2e
Debug e2e tests via VNC

Unless npm run e2e has been executed already, run the following command once:

yarn release-build

Next you'll be able to debug the e2e tests with the following command:

yarn e2e-vnc
Run e2e tests against the development environment
yarn e2e-dev
Run e2e tests against the development environment with a local Chrome: