Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testio MVP #119

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_URL=
45 changes: 45 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"parser": "@typescript-eslint/parser",
"root": true,
"extends": [
"airbnb-typescript",
"plugin:@typescript-eslint/recommended",
"plugin:import/typescript",
"plugin:react/recommended",
"plugin:prettier/recommended",
"prettier/react"
],
"env": {
"browser": true,
"jest": true
},
"rules": {
"import/prefer-default-export": 0,
"react/jsx-props-no-spreading": 0,
"react/require-default-props": 0,
"react/display-name": 0,
"no-plusplus": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/explicit-function-return-type": "off",
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
},
"plugins": ["@typescript-eslint", "jest", "prettier"],
"settings": {
"parser": "typescript-eslint-parser",
"plugins": ["import"],
"rules": {
"import/no-unresolved": "error"
},
"react": {
"version": "16.13"
}
},
"parserOptions": {
"ecmaVersion": 2018,
"project": "tsconfig.json",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
}
}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
node_modules
.idea
.DS_Store
.env
18 changes: 18 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"printWidth": 110,
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "avoid",
"overrides": [
{
"files": "*.md",
"options": {
"printWidth": 90,
"trailingComma": "none",
"proseWrap": "always"
}
}
]
}
4 changes: 4 additions & 0 deletions .storybook/addons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'storybook-addon-jsx/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-actions/register';
import 'storybook-formik/register';
44 changes: 44 additions & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { configure, addDecorator, addParameters } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
import { withInfo } from '@storybook/addon-info';
import { ThemeProvider } from 'styled-components';
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';

import { theme } from '../src/theme';
import { themeMui } from '../src/theme/themeMui';
import { GlobalStyles } from '../src/globalStyles';

addParameters({
options: {
panelPosition: 'right',
},
});

addDecorator(
withInfo({
inline: true,
header: false,
}),
);

addDecorator(story => (
<ThemeProvider theme={theme}>
<MuiThemeProvider theme={themeMui}>
<>
<GlobalStyles />
{story()}
</>
</MuiThemeProvider>
</ThemeProvider>
));

addDecorator(withKnobs);

const req = require.context('../src/components', true, /.stories.tsx/);

function loadStories() {
req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);
27 changes: 27 additions & 0 deletions .storybook/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const path = require('path');

module.exports = ({ config }) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve('ts-loader'),
options: {
transpileOnly: true,
},
},
{
loader: require.resolve('react-docgen-typescript-loader'),
},
],
resolve: {
alias: {
'@components': path.join(__dirname, '../src/components/'),
'@assets': path.join(__dirname, '../src/assets/'),
},
},
});
config.resolve.extensions.push('.ts', '.tsx');

return config;
};
73 changes: 29 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,42 @@
# Tesonet FrontEnd developer task
# Testio

## Basic instructions
## Tech-Stack / Tools

1. Fork this repo
1. Grab design files from [here](https://www.dropbox.com/sh/ql709t4h1ksl8jn/AACaARTQ9wUkpRNj07w2uHRka?dl=0).
If you don't have Sketch or Photoshop, there are always free options to preview design:
- [Avocode](https://avocode.com/) - just import `.sketch` file
- [Zeplin](https://zeplin.io/) - just import `.sketch` file
- [Figma](https://www.figma.com/) - just import `.sketch` file
1. Do your best with the task 💪
1. Prepare a pull request and let us know that you are done (feel free to add comment a about the task)
### Development

## Requirements
- [StyledComponents](https://www.styled-components.com/) for styling
- [Storybook](https://storybook.js.org/) for developing components in isolation

### Design
### Code Quality

- Design should be recreated as per provided design file. We aren't talking about pixel perfect, we know there are gazillion screen sizes these days, just follow best UI/UX patterns, don't invent new icons, colors or spacing and you're all good! 👍
- Design must be mobile-firendly and responsive.
- Use `SVG`'s where possible
- For `CSS` you can use whatever you need and feel comfortable with (vanilla `CSS` is an option too), but we strongly recommend these:
- pre-processor ([`SCSS`](https://sass-lang.com/))
- [`CSS-in-JS`](https://reactjs.org/docs/faq-styling.html#what-is-css-in-js) library ([`styled-components`](https://www.styled-components.com/), [`JSS`](https://cssinjs.org/), [`emotion`](https://github.com/emotion-js/emotion), [`aphrodite`](https://github.com/Khan/aphrodite))
- [`BEM`](http://getbem.com/introduction/) methodology
- [TypeScript](https://www.typescriptlang.org/) for static typing
- [Jest](https://facebook.github.io/jest/) with
[React Testing Library](https://testing-library.com/docs/react-testing-library/intro)
for testing
- [prettier](https://prettier.io/) for consistent source-code formating
- [eslint](https://eslint.org/) for static code analysis

### App
## Installing

- Use ES6+ features where applicable
- Use [`react.js`](https://reactjs.org/)
- Use state management solution ([`redux`](https://redux.js.org/) preferably). We know it is possible to do without, but we are curious - can you do with?
- This must be a single page application. Use routing library([`react-router-dom`](https://www.npmjs.com/package/react-router-dom) or [`@reach/router`](https://reach.tech/router))
- Implement login by sending an authorization request (`POST`) to https://playground.tesonet.lt/v1/tokens to generate a token (don't forget to pass `Content-Type`):
Install npm dependencies `npm install`.

```json
{ "username": "tesonet", "password": "partyanimal" }
```
## Development

Create a `.env` file as per example.

- Use browser storage solution to persist token between sessions
- Use the token to retrieve the server list from https://playground.tesonet.lt/v1/servers,
- Order the results of servers list by `distance` and `name`.
- Implement logout (don't forget about the token in the storage)
- Your app must work on all modern browsers and IE11+ 🐢🤷
Run the app in development mode.

### Bonus
```
npm run dev
```

- It is all good to use [`create-react-app`](https://github.com/facebook/create-react-app) as a starter, but if you have time and want showcase your skill - use JS bundler ([`Webpack`](https://webpack.js.org/) preferred) 📦📦📦
- We highly recommend following `TDD` patterns and showcasing your skills at writing tests(`unit`, `integration`, `e2e` - all are good)
- Use [`npm scripts`](https://docs.npmjs.com/misc/scripts) for running tasks, i.e. for development, clening build or etc.
- Do validation of login fields and provide user friendly error messages if needed **#UXmatters**
- Indicate loading state for the user whenever requests are in action and user might not understand they needs to wait
Open [http://localhost:3000](http://localhost:3000) to view it in the browser. The page
will automatically reload if you make changes to the code.

## Few tips
Run storybook.

```
npm run storybook
```

- Imagine this as a production level product at scale 😉
- Structure! With great structure, comes great reusability!
- Maybe You have an idea that is not in the task? Do it! It's on you!
- Have fun! 🎉🎉🎉
Open [http://localhost:6006](http://localhost:6006) to view it in the browser.
9 changes: 9 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
presets: [['@babel/env', { modules: false }], '@babel/preset-react', '@babel/typescript'],
env: {
test: {
presets: [['@babel/preset-env']],
},
},
plugins: ['@babel/plugin-transform-runtime'],
};
19 changes: 19 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = {
roots: ['<rootDir>/src'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
setupFilesAfterEnv: ['<rootDir>/jest/setupTests.ts'],
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', 'png', 'jpg'],
moduleNameMapper: {
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/jest/fileMock.js',
'^@components(.*)$': '<rootDir>/src/components$1',
'^@assets(.*)$': '<rootDir>/src/assets$1',
'^@theme(.*)$': '<rootDir>/src/theme$1',
'^@redux(.*)$': '<rootDir>/src/redux$1',
'^@utils(.*)$': '<rootDir>/src/utils$1',
'^@hooks(.*)$': '<rootDir>/src/hooks$1',
},
};
1 change: 1 addition & 0 deletions jest/fileMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = '';
3 changes: 3 additions & 0 deletions jest/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import '@testing-library/jest-dom';

jest.mock('axios');
Loading