Latest playable version: https://tictactoe-elixir-online.herokuapp.com
This project implements TicTacToe as a client-server application so the game is playable via browser. Backend made on Elixir and it's web framework Phoenix. Fronted is implemented as a Flux RaectJS site utilizing React-Redux package to manage UI state.
To start the game from sourcecode:
- Navigate to the project's folder via terminal.
- Install dependencies with
mix deps.get
- Install Node.js dependencies with
npm --prefix assets install
- Start Phoenix endpoint with
mix phx.server
You should see something like this in your terminal
The game is running, visit localhost:4000
from your browser to play.
The folder structure of this project is dictated by 2 major factors:
- Our deployment server of choice is Heroku. It demands root folder to have Phoenix application.
- Phoenix framework by default creates a folder structure that we see in the project root.
-- lib
folder is the folder of our server code
-- assets
- the folder with our client's code
-- other folders
---- priv
- auto-generated by Phoenix. No changes there
---- config
- contains configurations for run environments
-- test
- place for our server unit and integration tests
-- tests_e2e
- place for end-to-end tests. End-to-end tests are implemented as screenshot testing using Cypress.io framework. This framework also demands certain structure of the folders of our the tests directory.
The solution is a client-server application with
- Traditional RESTful API server having onion structure and written using a functional language
- Flux client website implemented on ReactJS and React-Redux
- Read and Write responsibilities are separated
- Game state machine being distributed between client and server
- 2-way communication done via polling data by client
Last 3 characteristics are the result of preparing the system for PvP play feature, which, unfortunately, is not in the game yet.
More details on the Architecture wiki page.
First of all it is a research project. Some of the outcomes of numerous researches could be found on the corresponding wiki page
Is a ReactJS application, managing UI state utilizing Flux structure and React-Redux package.
- Send user commands (Start game, make move)
- Display current game state
Commands are sent via POST and PUT requests to the game server. Current game state is fetched by continuous polling data from the server via GET requests.
Client source code is in the assets
folder of the solution.
- It's
js
folder contains all the ReactJS components. app.js
is the entry point of the client./js/components
- folder with actual components/screens.- Folders
reducers
,containers
,actions
contains React-Redux serving parts /assets/css/app.css
the file with our custom. css styles.
Important moment:
Due to Phoenix specifics, app.js
must have row import appCss from './../css/app.css'
in order to hook up our custom styles.
More details on the Game client wiki page
Is a webserver implemented using Elixir language and it's web framework Phoenix. Server designed in a layered manner, keeping all workers with side effects on the outer isolating them from workers with pure domain logic.
- Execute commands and change game state accordingly
- Persist current game state
Due to Phoenix template server logic is located in lib
folder. And split between 2 nested folders:
tictactoe
- Pure domain logictictactoe_web
- Phoenix infrastructure and controllers
Endpoint |
---|
POST /start_game |
GET /game/{game_id} |
PUT /make_move/{game_id} |
GET /version |
Routing is defined in /tictactoe_web/router.ex
So in case of adding new endpoints, this file must be also extended.
More details on the Game server wiki page
The system is covered with 3 types of tests.
From bottom to top
Are covering server-side domain and side-effects logic.
The tests are located in the test
folder in tictactoe
and tictactoe_web
directories.
The tests doesn't use any mocks but quite extensively use randomized fakes defined in test_helper.exs
- Navigate to the project's folder via terminal.
- Install dependencies with
mix deps.get
- Start Phoenix endpoint with
mix test
Are the highest level tests in the solution. They run against the UI simulating complete use cases.
These tests has a bit more complicated infrastructure, since they need a UI testing framework. Our framework of choice is cypress.io.
Important, that the tests are the snapshot tests, meaning that that they preform some actions with the UI, than taking a screenshot and compare it with approved images. It makes tests text plain and simple, but unfortunately this kind of tests if very fragile when they executed by CI\CD pipeline.
- Download cypress.io
-- Open test_e2e folder in project from cypress application
-- Run all tests
- Run via terminals
-- In first terminal instance start our server as it is described in the Running the application section
-- Open second terminal instance and:
--- Navigate to test_e2e
folder of the project
--- Install required dependencies npm install
--- Execute tests npx cypress run
More details on the Testing wiki page
The app is deployed to Heroku servers. In order to deploy a Phoenix app elixir_buildpack.config is needed
Our CI/CD server of choice is Travis Solution's deployment script is .travis.yml And since our end-to-end tests are doing snapshot comparisons, deployment script uses another bash script upload_screenshots.sh to provide developers with resulting screenshots and differences in case of failures.