1
0
mirror of https://github.com/danbee/chess synced 2025-03-04 08:39:06 +00:00

Compare commits

..

12 Commits

86 changed files with 4789 additions and 1973 deletions

View File

@ -1,3 +1,4 @@
https://github.com/gigalixir/gigalixir-buildpack-clean-cache.git
https://github.com/HashNuke/heroku-buildpack-elixir https://github.com/HashNuke/heroku-buildpack-elixir
https://github.com/gjaldon/heroku-buildpack-phoenix-static https://github.com/gjaldon/heroku-buildpack-phoenix-static
https://github.com/gigalixir/gigalixir-buildpack-mix.git https://github.com/gigalixir/gigalixir-buildpack-distillery.git

View File

@ -1,3 +0,0 @@
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@ -1,4 +1,4 @@
elixir 1.14.1 elixir 1.11.3
python 3.9.1 python 2.7.14
nodejs 16.14.0 nodejs 10.16.0
erlang 24.2.1 erlang 23.2.3

View File

@ -1,42 +0,0 @@
FROM --platform=linux/amd64 elixir:1.14.1
# Create a directory for your application code and set it as the WORKDIR. All following commands will be run in this directory.
RUN mkdir /app
WORKDIR /app
# Update package repo
RUN apt-get update
# Install Chrome
RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
apt-get -y install ./google-chrome-stable_current_amd64.deb
# Install ChromeDriver
RUN CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
mkdir -p /opt/chromedriver-$CHROMEDRIVER_VERSION && \
curl -sS -o /tmp/chromedriver_linux64.zip http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_VERSION/chromedriver_linux64.zip && \
unzip -qq /tmp/chromedriver_linux64.zip -d /opt/chromedriver-$CHROMEDRIVER_VERSION && \
rm /tmp/chromedriver_linux64.zip && \
chmod +x /opt/chromedriver-$CHROMEDRIVER_VERSION/chromedriver && \
ln -fs /opt/chromedriver-$CHROMEDRIVER_VERSION/chromedriver /usr/local/bin/chromedriver
# Install NodeJS
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
apt-get install nodejs
# Install Yarn
RUN npm install --global yarn
# Install Rebar and Hex
RUN mix local.rebar --force && mix local.hex --force
# Install the Phoenix Mix archive
RUN mix archive.install --sha512 2a2f5167f5ea30f314500da449dbd8cfb4b6986cc27197c82fa4cc328798814f89a4dbe0183a5f213faed3587e8133ce99c1fab74cf1597978a270bdcc7bf789 --force https://github.com/phoenixframework/archives/raw/master/phx_new.ez
# COPY mix.exs and mix.lock and install dependencies before adding the full code so the cache only
# gets invalidated when dependencies are changed
COPY mix.exs mix.lock ./
RUN mix deps.get
# Copy the app source code into the image
COPY ./ /app

View File

@ -1,5 +1,3 @@
@use "sass:math";
.opponent-finder__result { .opponent-finder__result {
border-bottom: 1px dotted $black; border-bottom: 1px dotted $black;
border-bottom-left-radius: $base-border-radius; border-bottom-left-radius: $base-border-radius;
@ -7,14 +5,14 @@
border-left: 1px dotted $black; border-left: 1px dotted $black;
border-right: 1px dotted $black; border-right: 1px dotted $black;
margin-top: -$small-spacing; margin-top: -$small-spacing;
padding: math.div($small-spacing, 3); padding: $small-spacing / 3;
} }
.opponent-finder__result-item { .opponent-finder__result-item {
border-radius: $base-border-radius * 0.5; border-radius: $base-border-radius / 2;
cursor: pointer; cursor: pointer;
display: block; display: block;
padding: math.div($small-spacing, 3) $base-spacing * 0.5; padding: $small-spacing / 3 $base-spacing / 2;
text-decoration: none; text-decoration: none;
&:hover, &:hover,

View File

@ -1,5 +1,3 @@
@use "sass:math";
$_form-background-color: $background-color; $_form-background-color: $background-color;
fieldset { fieldset {
@ -11,14 +9,14 @@ fieldset {
legend { legend {
font-weight: $heavy-font-weight; font-weight: $heavy-font-weight;
margin-bottom: $small-spacing * 0.5; margin-bottom: $small-spacing / 2;
padding: 0; padding: 0;
} }
label { label {
display: block; display: block;
font-weight: $heavy-font-weight; font-weight: $heavy-font-weight;
margin-bottom: $small-spacing * 0.5; margin-bottom: $small-spacing / 2;
} }
input, input,
@ -37,7 +35,7 @@ textarea {
box-sizing: border-box; box-sizing: border-box;
color: $foreground-color; color: $foreground-color;
margin-bottom: $small-spacing; margin-bottom: $small-spacing;
padding: math.div($base-spacing, 3); padding: $base-spacing / 3;
transition: border-color $base-duration $base-timing; transition: border-color $base-duration $base-timing;
width: 100%; width: 100%;

View File

@ -1,7 +1,7 @@
$base-border-radius: 0.5rem; $base-border-radius: 0.5rem;
$base-spacing: 2rem; $base-spacing: 2rem;
$small-spacing: $base-spacing * 0.5; $small-spacing: $base-spacing / 2;
$x-small-spacing: $small-spacing * 0.5; $x-small-spacing: $small-spacing / 2;
$base-z-index: 0; $base-z-index: 0;
$container-width: 90%; $container-width: 90%;

View File

@ -130,7 +130,7 @@
/// @content [Write the style you want to apply to the children, and it will be added within the @content directive] /// @content [Write the style you want to apply to the children, and it will be added within the @content directive]
/// @param {number} $num - id of the child /// @param {number} $num - id of the child
@mixin middle($num) { @mixin middle($num) {
&:nth-child(#{round($num * 0.5)}) { &:nth-child(#{round($num / 2)}) {
@content; @content;
} }
} }

View File

@ -67,8 +67,6 @@
/// ///
/// @require {function} _fetch-bourbon-setting /// @require {function} _fetch-bourbon-setting
@use "sass:math";
@function modular-scale( @function modular-scale(
$increment, $increment,
$value: _fetch-bourbon-setting("modular-scale-base"), $value: _fetch-bourbon-setting("modular-scale-base"),
@ -80,7 +78,7 @@
// scale $v2 to just above $v1 // scale $v2 to just above $v1
@while $v2 > $v1 { @while $v2 > $v1 {
$v2: math.div($v2, $ratio); // will be off-by-1 $v2: ($v2 / $ratio); // will be off-by-1
} }
@while $v2 < $v1 { @while $v2 < $v1 {
$v2: ($v2 * $ratio); // will fix off-by-1 $v2: ($v2 * $ratio); // will fix off-by-1
@ -104,15 +102,15 @@
@if $increment < 0 { @if $increment < 0 {
// adjust $v2 to just below $v1 // adjust $v2 to just below $v1
@if $double-stranded { @if $double-stranded {
$v2: math.div($v2, $ratio); $v2: ($v2 / $ratio);
} }
@for $i from $increment through -1 { @for $i from $increment through -1 {
@if $double-stranded and math.div($v1, $ratio) < $v2 { @if $double-stranded and ($v1 / $ratio) < $v2 {
$value: $v2; $value: $v2;
$v2: math.div($v2, $ratio); $v2: ($v2 / $ratio);
} @else { } @else {
$v1: math.div($v1, $ratio); $v1: ($v1 / $ratio);
$value: $v1; $value: $v1;
} }
} }

View File

@ -12,8 +12,6 @@
/// // Output /// // Output
/// $dimension: 10; /// $dimension: 10;
@use "sass:math";
@function strip-unit($value) { @function strip-unit($value) {
@return math.div($value, $value * 0 + 1); @return ($value / ($value * 0 + 1));
} }

View File

@ -55,25 +55,25 @@
@if $direction == "up" { @if $direction == "up" {
border-color: transparent transparent $color; border-color: transparent transparent $color;
border-width: 0 ($width * 0.5) $height; border-width: 0 ($width / 2) $height;
} @else if $direction == "up-right" { } @else if $direction == "up-right" {
border-color: transparent $color transparent transparent; border-color: transparent $color transparent transparent;
border-width: 0 $width $width 0; border-width: 0 $width $width 0;
} @else if $direction == "right" { } @else if $direction == "right" {
border-color: transparent transparent transparent $color; border-color: transparent transparent transparent $color;
border-width: ($height * 0.5) 0 ($height * 0.5) $width; border-width: ($height / 2) 0 ($height / 2) $width;
} @else if $direction == "down-right" { } @else if $direction == "down-right" {
border-color: transparent transparent $color; border-color: transparent transparent $color;
border-width: 0 0 $width $width; border-width: 0 0 $width $width;
} @else if $direction == "down" { } @else if $direction == "down" {
border-color: $color transparent transparent; border-color: $color transparent transparent;
border-width: $height ($width * 0.5) 0; border-width: $height ($width / 2) 0;
} @else if $direction == "down-left" { } @else if $direction == "down-left" {
border-color: transparent transparent transparent $color; border-color: transparent transparent transparent $color;
border-width: $width 0 0 $width; border-width: $width 0 0 $width;
} @else if $direction == "left" { } @else if $direction == "left" {
border-color: transparent $color transparent transparent; border-color: transparent $color transparent transparent;
border-width: ($height * 0.5) $width ($height * 0.5) 0; border-width: ($height / 2) $width ($height / 2) 0;
} @else if $direction == "up-left" { } @else if $direction == "up-left" {
border-color: $color transparent transparent; border-color: $color transparent transparent;
border-width: $width $width 0 0; border-width: $width $width 0 0;

View File

@ -19,15 +19,13 @@
/// ///
/// @access private /// @access private
@use "sass:math";
@function _contrast-ratio($color-1, $color-2) { @function _contrast-ratio($color-1, $color-2) {
$-local-lightness-1: _lightness($color-1) + 0.05; $-local-lightness-1: _lightness($color-1) + 0.05;
$-local-lightness-2: _lightness($color-2) + 0.05; $-local-lightness-2: _lightness($color-2) + 0.05;
@if $-local-lightness-1 > $-local-lightness-2 { @if $-local-lightness-1 > $-local-lightness-2 {
@return math.div($-local-lightness-1, $-local-lightness-2); @return $-local-lightness-1 / $-local-lightness-2;
} @else { } @else {
@return math.div($-local-lightness-2, $-local-lightness-1); @return $-local-lightness-2 / $-local-lightness-1;
} }
} }

View File

@ -11,13 +11,11 @@
/// ///
/// @access private /// @access private
@use "sass:math";
@function _gamma($channel) { @function _gamma($channel) {
@if $channel < 0.03928 { @if $channel < 0.03928 {
@return math.div($channel, 12.92); @return $channel / 12.92;
} @else { } @else {
$c: math.div($channel + 0.055, 1.055); $c: ($channel + 0.055) / 1.055;
@return math.div(133 * $c * $c * $c + 155 * $c * $c, 288); @return (133 * $c * $c * $c + 155 * $c * $c) / 288;
} }
} }

View File

@ -11,16 +11,14 @@
/// ///
/// @access private /// @access private
@use "sass:math";
@function _lightness($hex-color) { @function _lightness($hex-color) {
$-local-red-raw: red(rgba($hex-color, 1)); $-local-red-raw: red(rgba($hex-color, 1));
$-local-green-raw: green(rgba($hex-color, 1)); $-local-green-raw: green(rgba($hex-color, 1));
$-local-blue-raw: blue(rgba($hex-color, 1)); $-local-blue-raw: blue(rgba($hex-color, 1));
$-local-red: _gamma(math.div($-local-red-raw, 255)); $-local-red: _gamma($-local-red-raw / 255);
$-local-green: _gamma(math.div($-local-green-raw, 255)); $-local-green: _gamma($-local-green-raw / 255);
$-local-blue: _gamma(math.div($-local-blue-raw, 255)); $-local-blue: _gamma($-local-blue-raw / 255);
@return $-local-red * 0.2126 + $-local-green * 0.7152 + $-local-blue * 0.0722; @return $-local-red * 0.2126 + $-local-green * 0.7152 + $-local-blue * 0.0722;
} }

View File

@ -22,6 +22,8 @@ import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { createStore } from "redux"; import { createStore } from "redux";
import css from "../css/app.scss";
import Game from "./components/game"; import Game from "./components/game";
import OpponentFinder from "./components/opponent-finder"; import OpponentFinder from "./components/opponent-finder";
import chessBoardReducer from "./reducers/chess-board"; import chessBoardReducer from "./reducers/chess-board";

View File

@ -3,19 +3,19 @@
"description": " ", "description": " ",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"deploy": "cd .. && mix assets.deploy && rm -f _build/esbuild" "deploy": "webpack --mode production",
"watch": "webpack --mode development --watch-stdin"
}, },
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.12.1", "@babel/polyfill": "^7.12.1",
"axios": "^0.21.0", "axios": "^0.21.0",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"esbuild": "^0.14.21",
"gettext.js": "^1.0.0", "gettext.js": "^1.0.0",
"immutable": "^3.8.2", "immutable": "^3.8.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"phoenix": "^1.7.0-rc.2", "phoenix": "file:../deps/phoenix",
"phoenix_html": "^3.2.0", "phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "^0.18.11", "phoenix_live_view": "file:../deps/phoenix_live_view",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-redux": "^7.2.4", "react-redux": "^7.2.4",
@ -24,7 +24,18 @@
"url-loader": "^4.1.1" "url-loader": "^4.1.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"copy-webpack-plugin": "^9.0.0",
"css-loader": "^5.2.6", "css-loader": "^5.2.6",
"mini-css-extract-plugin": "^1.6.0" "mini-css-extract-plugin": "^1.6.0",
"node-sass": "^6.0.0",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"sass-loader": "^12.1.0",
"terser-webpack-plugin": "^5.1.3",
"webpack": "^5.40.0",
"webpack-cli": "^4.7.2"
} }
} }

56
assets/webpack.config.js Normal file
View File

@ -0,0 +1,56 @@
const path = require("path");
const glob = require("glob");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = (env, options) => {
const devMode = options.mode !== "production";
return {
optimization: {
minimizer: [new TerserPlugin(), new OptimizeCSSAssetsPlugin({})],
},
entry: {
app: glob.sync("./vendor/**/*.js").concat(["./js/app.js"]),
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, "../priv/static/js"),
publicPath: "/js/",
},
devtool: devMode ? "eval-cheap-module-source-map" : undefined,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
{
test: /\.(png|jpg|gif|svg)$/i,
use: [
{
loader: "url-loader",
options: {
limit: 8192,
name: "[name].[hash:7].[ext]",
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: "../css/app.css" }),
new CopyWebpackPlugin({ patterns: [{ from: "static/", to: "../" }] }),
],
};
};

View File

@ -1,734 +0,0 @@
Arguments:
/Users/danbarber/.asdf/installs/nodejs/16.14.0/bin/node /Users/danbarber/.asdf/installs/yarn/1.22.10/bin/yarn.js add phoenix phoenix_html phoenix_live_view
PATH:
/Users/danbarber/.asdf/plugins/nodejs/shims:/Users/danbarber/.asdf/installs/nodejs/16.14.0/bin:/Users/danbarber/.asdf/installs/yarn/1.22.10/bin:/Users/danbarber/.bin:/usr/local/share/npm/bin:.git/safe/../../bin:/Users/danbarber/.asdf/shims:/opt/homebrew/bin/../opt/asdf/libexec/bin:/usr/local/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/usr/local/zfs/bin:/opt/X11/bin:/Library/Apple/usr/bin:/Applications/Wireshark.app/Contents/MacOS:/Applications/kitty.app/Contents/MacOS:/Users/danbarber/.fzf/bin
Yarn version:
1.22.10
Node version:
16.14.0
Platform:
darwin arm64
Trace:
Error: ENOENT: no such file or directory, open '/Users/danbarber/Library/Caches/Yarn/v6/npm-esbuild-linux-arm64-0.14.21-e05599ea6253b58394157da162d856f3ead62f9e-integrity/node_modules/esbuild-linux-arm64/.yarn-metadata.json'
npm manifest:
{
"repository": {},
"description": " ",
"license": "MIT",
"scripts": {
"deploy": "cd .. && mix assets.deploy && rm -f _build/esbuild"
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"axios": "^0.21.0",
"classnames": "^2.3.1",
"esbuild": "^0.14.21",
"gettext.js": "^1.0.0",
"immutable": "^3.8.2",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"redux": "^4.1.0",
"redux-watch": "^1.2.0",
"url-loader": "^4.1.1"
},
"devDependencies": {
"css-loader": "^5.2.6",
"mini-css-extract-plugin": "^1.6.0"
}
}
yarn manifest:
No manifest
Lockfile:
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@babel/polyfill@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96"
integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==
dependencies:
core-js "^2.6.5"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.12.1", "@babel/runtime@^7.9.2":
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
dependencies:
regenerator-runtime "^0.13.4"
"@types/hoist-non-react-statics@^3.3.0":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/json-schema@^7.0.6":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/react-redux@^7.1.16":
version "7.1.16"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21"
integrity sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react@*":
version "17.0.11"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.11.tgz#67fcd0ddbf5a0b083a0f94e926c7d63f3b836451"
integrity sha512-yFRQbD+whVonItSk7ZzP/L+gPTJVBkL/7shLEF+i9GC/1cV3JmUxEQz6+9ylhUpWSDuqo1N9qEvqS6vTj4USUA==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/scheduler@*":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==
ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
ajv@^6.12.5:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ansi-styles@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=
axios@^0.21.0:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies:
follow-redirects "^1.10.0"
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
chalk@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f"
integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=
dependencies:
ansi-styles "~1.0.0"
has-color "~0.1.0"
strip-ansi "~0.1.0"
classnames@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
colorette@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
core-js@^2.6.5:
version "2.6.12"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
css-loader@^5.2.6:
version "5.2.6"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.6.tgz#c3c82ab77fea1f360e587d871a6811f4450cc8d1"
integrity sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w==
dependencies:
icss-utils "^5.1.0"
loader-utils "^2.0.0"
postcss "^8.2.15"
postcss-modules-extract-imports "^3.0.0"
postcss-modules-local-by-default "^4.0.0"
postcss-modules-scope "^3.0.0"
postcss-modules-values "^4.0.0"
postcss-value-parser "^4.1.0"
schema-utils "^3.0.0"
semver "^7.3.5"
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
csstype@^3.0.2:
version "3.0.8"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
emojis-list@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
encoding@^0.1.11:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
dependencies:
iconv-lite "^0.6.2"
esbuild-android-arm64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.21.tgz#8842d0c3b7c81fbe2dc46ddb416ffd6eb822184b"
integrity sha512-Bqgld1TY0wZv8TqiQmVxQFgYzz8ZmyzT7clXBDZFkOOdRybzsnj8AZuK1pwcLVA7Ya6XncHgJqIao7NFd3s0RQ==
esbuild-darwin-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.21.tgz#ec7df02ad88ecf7f8fc23a3ed7917e07dea0c9c9"
integrity sha512-j+Eg+e13djzyYINVvAbOo2/zvZ2DivuJJTaBrJnJHSD7kUNuGHRkHoSfFjbI80KHkn091w350wdmXDNSgRjfYQ==
esbuild-darwin-arm64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.21.tgz#0c2a977edec1ef54097ee56a911518c820d4e5e4"
integrity sha512-nDNTKWDPI0RuoPj5BhcSB2z5EmZJJAyRtZLIjyXSqSpAyoB8eyAKXl4lB8U2P78Fnh4Lh1le/fmpewXE04JhBQ==
esbuild-freebsd-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.21.tgz#f5b5fc1d031286c3a0949d1bda7db774b7d0404e"
integrity sha512-zIurkCHXhxELiDZtLGiexi8t8onQc2LtuE+S7457H/pP0g0MLRKMrsn/IN4LDkNe6lvBjuoZZi2OfelOHn831g==
esbuild-freebsd-arm64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.21.tgz#a05cab908013e4992b31a675850b8c44eb468c0c"
integrity sha512-wdxMmkJfbwcN+q85MpeUEamVZ40FNsBa9mPq8tAszDn8TRT2HoJvVRADPIIBa9SWWwlDChIMjkDKAnS3KS/sPA==
esbuild-linux-32@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.21.tgz#638d244cc58b951f447addb4bade628d126ef84b"
integrity sha512-fmxvyzOPPh2xiEHojpCeIQP6pXcoKsWbz3ryDDIKLOsk4xp3GbpHIEAWP0xTeuhEbendmvBDVKbAVv3PnODXLg==
esbuild-linux-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.21.tgz#8eb634abee928be7e35b985fafbfef2f2e31397f"
integrity sha512-edZyNOv1ql+kpmlzdqzzDjRQYls+tSyi4QFi+PdBhATJFUqHsnNELWA9vMSzAaInPOEaVUTA5Ml28XFChcy4DA==
esbuild-linux-arm64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.21.tgz#e05599ea6253b58394157da162d856f3ead62f9e"
integrity sha512-t5qxRkq4zdQC0zXpzSB2bTtfLgOvR0C6BXYaRE/6/k8/4SrkZcTZBeNu+xGvwCU4b5dU9ST9pwIWkK6T1grS8g==
esbuild-linux-arm@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.21.tgz#1ae1078231cf689d3ba894a32d3723c0be9b91fd"
integrity sha512-aSU5pUueK6afqmLQsbU+QcFBT62L+4G9hHMJDHWfxgid6hzhSmfRH9U/f+ymvxsSTr/HFRU4y7ox8ZyhlVl98w==
esbuild-linux-mips64le@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.21.tgz#f05be62d126764e99b37edcac5bb49b78c7a8890"
integrity sha512-jLZLQGCNlUsmIHtGqNvBs3zN+7a4D9ckf0JZ+jQTwHdZJ1SgV9mAjbB980OFo66LoY+WeM7t3WEnq3FjI1zw4A==
esbuild-linux-ppc64le@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.21.tgz#592c98d82dad7982268ef8deed858c4566f07ab1"
integrity sha512-4TWxpK391en2UBUw6GSrukToTDu6lL9vkm3Ll40HrI08WG3qcnJu7bl8e1+GzelDsiw1QmfAY/nNvJ6iaHRpCQ==
esbuild-linux-riscv64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.21.tgz#0db7bd6f10d8f9afea973a7d6bf87b449b864b7b"
integrity sha512-fElngqOaOfTsF+u+oetDLHsPG74vB2ZaGZUqmGefAJn3a5z9Z2pNa4WpVbbKgHpaAAy5tWM1m1sbGohj6Ki6+Q==
esbuild-linux-s390x@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.21.tgz#254a9354d34c9d1b41a3e21d2ec9269cbbb2c5df"
integrity sha512-brleZ6R5fYv0qQ7ZBwenQmP6i9TdvJCB092c/3D3pTLQHBGHJb5zWgKxOeS7bdHzmLy6a6W7GbFk6QKpjyD6QA==
esbuild-netbsd-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.21.tgz#4cb783d060b02bf3b897a9a12cce2b3b547726f8"
integrity sha512-nCEgsLCQ8RoFWVV8pVI+kX66ICwbPP/M9vEa0NJGIEB/Vs5sVGMqkf67oln90XNSkbc0bPBDuo4G6FxlF7PN8g==
esbuild-openbsd-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.21.tgz#f886b93feefddbe573528fa4b421c9c6e2bc969b"
integrity sha512-h9zLMyVD0T73MDTVYIb/qUTokwI6EJH9O6wESuTNq6+XpMSr6C5aYZ4fvFKdNELW+Xsod+yDS2hV2JTUAbFrLA==
esbuild-sunos-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.21.tgz#3829e4d57d4cb6950837fe90b0b67cdfb37cf13a"
integrity sha512-Kl+7Cot32qd9oqpLdB1tEGXEkjBlijrIxMJ0+vlDFaqsODutif25on0IZlFxEBtL2Gosd4p5WCV1U7UskNQfXA==
esbuild-windows-32@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.21.tgz#b858a22d1a82e53cdc59310cd56294133f7a95e7"
integrity sha512-V7vnTq67xPBUCk/9UtlolmQ798Ecjdr1ZoI1vcSgw7M82aSSt0eZdP6bh5KAFZU8pxDcx3qoHyWQfHYr11f22A==
esbuild-windows-64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.21.tgz#7bb5a027d5720cf9caf18a4bedd11327208f1f12"
integrity sha512-kDgHjKOHwjfJDCyRGELzVxiP/RBJBTA+wyspf78MTTJQkyPuxH2vChReNdWc+dU2S4gIZFHMdP1Qrl/k22ZmaA==
esbuild-windows-arm64@0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.21.tgz#25df54521ad602c826b262ea2e7cc1fe80f5c2f5"
integrity sha512-8Sbo0zpzgwWrwjQYLmHF78f7E2xg5Ve63bjB2ng3V2aManilnnTGaliq2snYg+NOX60+hEvJHRdVnuIAHW0lVw==
esbuild@^0.14.21:
version "0.14.21"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.21.tgz#b3e05f900f1c4394f596d60d63d9816468f0f671"
integrity sha512-7WEoNMBJdLN993dr9h0CpFHPRc3yFZD+EAVY9lg6syJJ12gc5fHq8d75QRExuhnMkT2DaRiIKFThRvDWP+fO+A==
optionalDependencies:
esbuild-android-arm64 "0.14.21"
esbuild-darwin-64 "0.14.21"
esbuild-darwin-arm64 "0.14.21"
esbuild-freebsd-64 "0.14.21"
esbuild-freebsd-arm64 "0.14.21"
esbuild-linux-32 "0.14.21"
esbuild-linux-64 "0.14.21"
esbuild-linux-arm "0.14.21"
esbuild-linux-arm64 "0.14.21"
esbuild-linux-mips64le "0.14.21"
esbuild-linux-ppc64le "0.14.21"
esbuild-linux-riscv64 "0.14.21"
esbuild-linux-s390x "0.14.21"
esbuild-netbsd-64 "0.14.21"
esbuild-openbsd-64 "0.14.21"
esbuild-sunos-64 "0.14.21"
esbuild-windows-32 "0.14.21"
esbuild-windows-64 "0.14.21"
esbuild-windows-arm64 "0.14.21"
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
follow-redirects@^1.10.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43"
integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==
gettext-parser@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/gettext-parser/-/gettext-parser-1.1.0.tgz#2c5a6638d893934b9b55037d0ad82cb7004b2679"
integrity sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=
dependencies:
encoding "^0.1.11"
gettext.js@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/gettext.js/-/gettext.js-1.0.0.tgz#7fefb01512c134759c51166ab4d3db26a585ae1a"
integrity sha512-cpnxNL5C9SlD7ms/NSCuGsQdaVQmwCYn9MILWpYjSPMAkX4aD/5/qC+QgH4GCRY0OMEcSiVBsqgWMEoTcETggQ==
dependencies:
po2json "^0.4.0"
has-color@~0.1.0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
iconv-lite@^0.6.2:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
dependencies:
safer-buffer ">= 2.1.2 < 3.0.0"
icss-utils@^5.0.0, icss-utils@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
immutable@^3.8.2:
version "3.8.2"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json5@^2.1.2:
version "2.2.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
dependencies:
minimist "^1.2.5"
loader-utils@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==
dependencies:
big.js "^5.2.2"
emojis-list "^3.0.0"
json5 "^2.1.2"
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
mime-db@1.48.0:
version "1.48.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d"
integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==
mime-types@^2.1.27:
version "2.1.31"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b"
integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==
dependencies:
mime-db "1.48.0"
mini-css-extract-plugin@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.0.tgz#b4db2525af2624899ed64a23b0016e0036411893"
integrity sha512-nPFKI7NSy6uONUo9yn2hIfb9vyYvkFu95qki0e21DQ9uaqNKDP15DGpK0KnV6wDroWxPHtExrdEwx/yDQ8nVRw==
dependencies:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
webpack-sources "^1.1.0"
minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
nanoid@^3.1.23:
version "3.1.23"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
nomnom@1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
integrity sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=
dependencies:
chalk "~0.4.0"
underscore "~1.6.0"
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
object-path@^0.11.5:
version "0.11.5"
resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a"
integrity sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg==
"phoenix@file:../deps/phoenix":
version "1.6.6"
"phoenix_html@file:../deps/phoenix_html":
<<<<<<< HEAD
version "3.2.0"
=======
version "2.14.3"
"phoenix_live_view@file:../deps/phoenix_live_view":
version "0.15.3"
picomatch@^2.2.1, picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
"phoenix_live_view@file:../deps/phoenix_live_view":
version "0.15.3"
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
pinkie-promise@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
dependencies:
pinkie "^2.0.0"
pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
pkg-dir@^4.1.0, pkg-dir@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
dependencies:
find-up "^4.0.0"
>>>>>>> 7af5f8c (Install LiveView)
po2json@^0.4.0:
version "0.4.5"
resolved "https://registry.yarnpkg.com/po2json/-/po2json-0.4.5.tgz#47bb2952da32d58a1be2f256a598eebc0b745118"
integrity sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=
dependencies:
gettext-parser "1.1.0"
nomnom "1.8.1"
postcss-modules-extract-imports@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
postcss-modules-local-by-default@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c"
integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==
dependencies:
icss-utils "^5.0.0"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.1.0"
postcss-modules-scope@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
dependencies:
postcss-selector-parser "^6.0.4"
postcss-modules-values@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
dependencies:
icss-utils "^5.0.0"
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
version "6.0.6"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea"
integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==
dependencies:
cssesc "^3.0.0"
util-deprecate "^1.0.2"
postcss-value-parser@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
postcss@^8.2.15:
version "8.3.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709"
integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==
dependencies:
colorette "^1.2.2"
nanoid "^3.1.23"
source-map-js "^0.6.2"
prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.8.1"
punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
react-dom@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler "^0.20.2"
react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-redux@^7.2.4:
version "7.2.4"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225"
integrity sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==
dependencies:
"@babel/runtime" "^7.12.1"
"@types/react-redux" "^7.1.16"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.13.1"
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
redux-watch@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/redux-watch/-/redux-watch-1.2.0.tgz#b3a745e15855ef72db0e06a60a4b2fe3676d79a7"
integrity sha512-Ws4Q+e5zFGMyy1H709c1Ws8apSd6MqoJRIzBDHbI4nikome/IZWVTYXdQNz+VJxPjyX/h2E+lYEo41fXgjCF8g==
dependencies:
object-path "^0.11.5"
redux@^4.0.0, redux@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4"
integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==
dependencies:
"@babel/runtime" "^7.9.2"
regenerator-runtime@^0.13.4:
version "0.13.7"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
"safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
scheduler@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
schema-utils@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
dependencies:
"@types/json-schema" "^7.0.6"
ajv "^6.12.5"
ajv-keywords "^3.5.2"
semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
source-list-map@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
source-map-js@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
strip-ansi@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=
underscore@~1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
integrity sha1-izixDKze9jM3uLJOT/htRa6lKag=
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
url-loader@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2"
integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==
dependencies:
loader-utils "^2.0.0"
mime-types "^2.1.27"
schema-utils "^3.0.0"
util-deprecate@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
webpack-sources@^1.1.0:
version "1.4.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
dependencies:
source-list-map "^2.0.0"
source-map "~0.6.1"
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==

File diff suppressed because it is too large Load Diff

View File

@ -3,5 +3,5 @@
echo "Building assets" echo "Building assets"
cd assets cd assets
yarn install yarn install
yarn run deploy yarn run build
cd .. cd ..

View File

@ -6,8 +6,8 @@ source /dev/stdin <<< "$(curl -sSL https://raw.githubusercontent.com/codeship/sc
echo "Installing Elixir" echo "Installing Elixir"
source /dev/stdin <<< "$(curl -sSL https://raw.githubusercontent.com/codeship/scripts/master/languages/elixir.sh)" source /dev/stdin <<< "$(curl -sSL https://raw.githubusercontent.com/codeship/scripts/master/languages/elixir.sh)"
echo "Installing ChromeDriver" echo "Installing PhantomJS"
curl -sSL https://raw.githubusercontent.com/codeship/scripts/master/packages/chromedriver.sh | bash -s curl -sSL https://raw.githubusercontent.com/codeship/scripts/master/packages/phantomjs.sh | bash -s
echo "Installing NodeJS" echo "Installing NodeJS"
nvm install $NODE_VERSION nvm install $NODE_VERSION

View File

@ -1,18 +0,0 @@
# Docker Compose-like syntax, see here for details:
# https://documentation.codeship.com/pro/builds-and-configuration/services/
app:
build:
image: danbee/chess
dockerfile: Dockerfile
environment:
MIX_ENV: test
PGHOST: db
PGUSER: postgres
PGPASSWORD: password
depends_on:
- db
db:
image: healthcheck/postgres:alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password

View File

@ -1,9 +0,0 @@
# This is where we define the test steps that would be run in a Codeship Pro build.
# The build passes as long as every test step returns with a non-zero exit code.
# See here for more: https://documentation.codeship.com/pro/builds-and-configuration/steps/
- name: build_assets
command: bin/codeship_assets
service: app
- name: run_mix_test
command: /bin/bash -c 'mix ecto.create && mix test'
service: app

View File

@ -3,7 +3,7 @@
# #
# This configuration file is loaded before any dependency and # This configuration file is loaded before any dependency and
# is restricted to this project. # is restricted to this project.
import Config use Mix.Config
config :phoenix, :json_library, Jason config :phoenix, :json_library, Jason
@ -31,27 +31,8 @@ config :chess, Chess.Auth.Guardian,
secret_key: "vd2vXkrYTTFKSKmNMoS2/Hk4Fxn8BkyzsVArRkxJazdQ3mr6bI4YgAC6f8ODiWlM" secret_key: "vd2vXkrYTTFKSKmNMoS2/Hk4Fxn8BkyzsVArRkxJazdQ3mr6bI4YgAC6f8ODiWlM"
config :formulator, config :formulator,
validate: false, translate_error_module: ChessWeb.ErrorHelpers
translate_error_module: ChessWeb.ErrorHelpers
# Configure esbuild (the version is required)
config :esbuild,
version: "0.17.5",
default: [
args:
~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/* --loader:.js=jsx),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
# Configure dart_sass
config :dart_sass,
version: "1.58.0",
default: [
args: ~w(css/app.scss ../priv/static/assets/app.css),
cd: Path.expand("../assets", __DIR__)
]
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs" import_config "#{Mix.env}.exs"

View File

@ -1,4 +1,4 @@
import Config use Mix.Config
# For development, we disable any cache and enable # For development, we disable any cache and enable
# debugging and code reloading. # debugging and code reloading.
@ -10,7 +10,16 @@ config :chess, ChessWeb.Endpoint,
http: [port: 4000], http: [port: 4000],
debug_errors: true, debug_errors: true,
code_reloader: true, code_reloader: true,
check_origin: false check_origin: false,
watchers: [
node: [
"node_modules/webpack/bin/webpack.js",
"--mode",
"development",
"--watch",
cd: Path.expand("../assets", __DIR__)
]
]
# Watch static and templates for browser reloading. # Watch static and templates for browser reloading.
config :chess, ChessWeb.Endpoint, config :chess, ChessWeb.Endpoint,

View File

@ -1,8 +1,8 @@
import Config use Mix.Config
config :chess, ChessWeb.Endpoint, config :chess, ChessWeb.Endpoint,
cache_static_manifest: "priv/static/cache_manifest.json", cache_static_manifest: "priv/static/cache_manifest.json",
check_origin: ["https://chess.danbee.in", "https://64squares.club"], check_origin: ["https://chess.danbarber.me", "https://64squares.club"],
http: [port: {:system, "PORT"}], http: [port: {:system, "PORT"}],
root: "./assets", root: "./assets",
secret_key_base: System.get_env("SECRET_KEY_BASE"), secret_key_base: System.get_env("SECRET_KEY_BASE"),

View File

@ -1,70 +0,0 @@
import Config
# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.
# Start the phoenix server if environment is set and running in a release
if System.get_env("PHX_SERVER") && System.get_env("RELEASE_NAME") do
config :chess, ChessWeb.Endpoint, server: true
end
if config_env() == :prod do
# The secret key base is used to sign/encrypt cookies and other secrets.
# A default value is used in config/dev.exs and config/test.exs but you
# want to use a different value for prod and you most likely don't want
# to check this value into version control, so we use an environment
# variable instead.
secret_key_base =
System.get_env("SECRET_KEY_BASE") ||
raise """
environment variable SECRET_KEY_BASE is missing.
You can generate one by calling: mix phx.gen.secret
"""
host = System.get_env("PHX_HOST") || "example.com"
port = String.to_integer(System.get_env("PORT") || "4000")
config :chess, ChessWeb.Endpoint,
url: [host: host, port: 443],
http: [
# Enable IPv6 and bind on all interfaces.
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
# See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
# for details about using IPv6 vs IPv4 and loopback vs public addresses.
ip: {0, 0, 0, 0, 0, 0, 0, 0},
port: port
],
secret_key_base: secret_key_base
# ## Using releases
#
# If you are doing OTP releases, you need to instruct Phoenix
# to start each relevant endpoint:
#
# config :<%= @web_app_name %>, <%= @endpoint_module %>, server: true
#
# Then you can assemble a release by calling `mix release`.
# See `mix help release` for more information.<%= if @mailer do %>
# ## Configuring the mailer
#
# In production you need to configure the mailer to use a different adapter.
# Also, you may need to configure the Swoosh API client of your choice if you
# are not using SMTP. Here is an example of the configuration:
#
# config :<%= @app_name %>, <%= @app_module %>.Mailer,
# adapter: Swoosh.Adapters.Mailgun,
# api_key: System.get_env("MAILGUN_API_KEY"),
# domain: System.get_env("MAILGUN_DOMAIN")
#
# For this example you need include a HTTP client required by Swoosh API client.
# Swoosh supports Hackney and Finch out of the box:
#
# config :swoosh, :api_client, Swoosh.ApiClient.Hackney
#
# See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.<% end %>
end

View File

@ -1,4 +1,4 @@
import Config use Mix.Config
# We don't run a server during test. If one is required, # We don't run a server during test. If one is required,
# you can enable the server option below. # you can enable the server option below.
@ -18,7 +18,7 @@ config :chess, Chess.Mailer, adapter: Bamboo.TestAdapter
config :chess, Chess.Repo, config :chess, Chess.Repo,
adapter: Ecto.Adapters.Postgres, adapter: Ecto.Adapters.Postgres,
database: "chess_test", database: "chess_test",
hostname: System.get_env("PGHOST") || "localhost", hostname: "localhost",
port: System.get_env("POSTGRES_PORT") || "5432", port: System.get_env("POSTGRES_PORT") || "5432",
pool: Ecto.Adapters.SQL.Sandbox pool: Ecto.Adapters.SQL.Sandbox

View File

@ -1,19 +0,0 @@
version: '3'
services:
app:
build: .
command: /bin/bash -c 'mix ecto.create && mix phx.server'
ports:
- "4000:4000"
environment:
MIX_ENV: dev
PGHOST: db
PGUSER: postgres
PGPASSWORD: password
links:
- db
db:
image: healthcheck/postgres:alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password

View File

@ -1,5 +1,5 @@
# Erlang version # Erlang version
erlang_version=OTP-24.2.1 erlang_version=23.2.3
# Elixir version # Elixir version
elixir_version=1.14.1 elixir_version=1.11.3

View File

@ -11,7 +11,7 @@ defmodule Chess do
{Phoenix.PubSub, [name: Chess.PubSub, adapter: Phoenix.PubSub.PG2]}, {Phoenix.PubSub, [name: Chess.PubSub, adapter: Phoenix.PubSub.PG2]},
{Chess.Repo, []}, {Chess.Repo, []},
{ChessWeb.Endpoint, []}, {ChessWeb.Endpoint, []},
{ChessWeb.Presence, []} {ChessWeb.Presence, []},
] ]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html

View File

@ -4,6 +4,7 @@ defmodule Chess.Auth do
""" """
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Comeonin.Argon2
alias Chess.Repo alias Chess.Repo
alias Chess.Store.User alias Chess.Store.User
@ -40,13 +41,11 @@ defmodule Chess.Auth do
@doc false @doc false
def authenticate_user(email, password) do def authenticate_user(email, password) do
query = query = from u in User,
from(u in User, where: u.email == ^email
where: u.email == ^email
)
query query
|> Repo.one() |> Repo.one
|> Argon2.check_pass(password) |> Argon2.check_pass(password)
end end
end end

View File

@ -12,7 +12,6 @@ defmodule Chess.Auth.ErrorHandler do
|> put_flash(:info, "You must be logged in") |> put_flash(:info, "You must be logged in")
|> redirect(to: "/") |> redirect(to: "/")
|> halt() |> halt()
"json" -> "json" ->
conn conn
|> put_status(403) |> put_status(403)

View File

@ -10,9 +10,8 @@ defmodule Chess.Auth.Guardian do
end end
def resource_from_claims(claims) do def resource_from_claims(claims) do
user = user = claims["sub"]
claims["sub"] |> Auth.get_user!
|> Auth.get_user!()
{:ok, user} {:ok, user}
end end

View File

@ -7,11 +7,11 @@ defmodule Chess.Auth.Pipeline do
module: Chess.Auth.Guardian module: Chess.Auth.Guardian
# If there is a session token, validate it # If there is a session token, validate it
plug(Guardian.Plug.VerifySession, claims: %{"typ" => "access"}) plug Guardian.Plug.VerifySession, claims: %{"typ" => "access"}
# If there is an authorization header, validate it # If there is an authorization header, validate it
plug(Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}) plug Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}
# Load the user if either of the verifications worked # Load the user if either of the verifications worked
plug(Guardian.Plug.LoadResource, allow_blank: true) plug Guardian.Plug.LoadResource, allow_blank: true
end end

View File

@ -3,10 +3,12 @@ defmodule Chess.Board do
def transform(board) do def transform(board) do
Enum.map(0..7, fn rank -> Enum.map(0..7, fn rank ->
Enum.map(0..7, fn file -> {rank,
board Enum.map(0..7, fn file ->
|> piece({file, rank}) {file,
end) board
|> piece({file, rank})}
end)}
end) end)
end end
@ -31,8 +33,8 @@ defmodule Chess.Board do
end end
def move_piece(board, %{ def move_piece(board, %{
"from" => [from_file, from_rank], from: {from_file, from_rank},
"to" => [to_file, to_rank] to: {to_file, to_rank}
}) do }) do
{piece, board} = Map.pop(board, to_index({from_file, from_rank})) {piece, board} = Map.pop(board, to_index({from_file, from_rank}))
{piece_captured, board} = Map.pop(board, to_index({to_file, to_rank})) {piece_captured, board} = Map.pop(board, to_index({to_file, to_rank}))
@ -67,15 +69,15 @@ defmodule Chess.Board do
def castling_move(board, %{from: {4, rank}, to: {2, _rank}}) do def castling_move(board, %{from: {4, rank}, to: {2, _rank}}) do
move_piece(board, %{ move_piece(board, %{
"from" => [0, rank], from: {0, rank},
"to" => [3, rank] to: {3, rank}
}) })
end end
def castling_move(board, %{"from" => [4, rank], "to" => [6, _rank]}) do def castling_move(board, %{from: {4, rank}, to: {6, _rank}}) do
move_piece(board, %{ move_piece(board, %{
"from" => [7, rank], from: {7, rank},
"to" => [5, rank] to: {5, rank}
}) })
end end

View File

@ -12,7 +12,9 @@ defmodule Chess.Emails do
new_email() new_email()
|> to(game.opponent) |> to(game.opponent)
|> from({"64squares", "games@64squares.club"}) |> from({"64squares", "games@64squares.club"})
|> subject("[64squares] #{game.user.name} has invited you to play a game of chess.") |> subject(
"[64squares] #{game.user.name} has invited you to play a game of chess."
)
|> text_body(""" |> text_body("""
Game link: #{Helpers.game_url(conn, :show, game)} Game link: #{Helpers.game_url(conn, :show, game)}
""") """)
@ -25,7 +27,9 @@ defmodule Chess.Emails do
new_email() new_email()
|> to(opponent) |> to(opponent)
|> from({"64squares", "games@64squares.club"}) |> from({"64squares", "games@64squares.club"})
|> subject("[64squares] #{user.name} has moved.") |> subject(
"[64squares] #{user.name} has moved."
)
|> text_body(""" |> text_body("""
Game link: #{Helpers.game_url(socket, :show, game)} Game link: #{Helpers.game_url(socket, :show, game)}
""") """)

View File

@ -5,7 +5,7 @@ defmodule Chess.MoveList do
def transform(moves) do def transform(moves) do
moves moves
|> Enum.map(&Move.transform(&1)) |> Enum.map(&(Move.transform(&1)))
|> Enum.chunk_every(2) |> Enum.chunk_every(2)
end end
end end

View File

@ -22,17 +22,13 @@ defmodule Chess.Moves.Generator do
defp _moves(_colour, _board, {_file, 0}, {_, -1}), do: [] defp _moves(_colour, _board, {_file, 0}, {_, -1}), do: []
defp _moves(_colour, _board, {7, _rank}, {1, _}), do: [] defp _moves(_colour, _board, {7, _rank}, {1, _}), do: []
defp _moves(_colour, _board, {_file, 7}, {_, 1}), do: [] defp _moves(_colour, _board, {_file, 7}, {_, 1}), do: []
defp _moves(colour, board, {file, rank}, {fv, rv}) do defp _moves(colour, board, {file, rank}, {fv, rv}) do
next_square = {file + fv, rank + rv} next_square = {file + fv, rank + rv}
cond do cond do
can_capture_piece?(colour, board, next_square) -> can_capture_piece?(colour, board, next_square) ->
[next_square] [next_square]
obstruction?(colour, board, next_square) -> obstruction?(colour, board, next_square) ->
[] []
true -> true ->
[next_square | _moves(colour, board, next_square, {fv, rv})] [next_square | _moves(colour, board, next_square, {fv, rv})]
end end
@ -40,18 +36,14 @@ defmodule Chess.Moves.Generator do
# Move generation for pieces that follow a pattern # Move generation for pieces that follow a pattern
defp _moves(_colour, _board, {_file, _rank}, []), do: [] defp _moves(_colour, _board, {_file, _rank}, []), do: []
defp _moves(colour, board, {file, rank}, [{fv, rv} | moves]) do defp _moves(colour, board, {file, rank}, [{fv, rv} | moves]) do
move_square = {file + fv, rank + rv} move_square = {file + fv, rank + rv}
cond do cond do
outside_board?(move_square) || outside_board?(move_square) ||
obstruction?(colour, board, move_square) -> obstruction?(colour, board, move_square) ->
_moves(colour, board, {file, rank}, moves) _moves(colour, board, {file, rank}, moves)
can_capture_piece?(colour, board, move_square) -> can_capture_piece?(colour, board, move_square) ->
[move_square | _moves(colour, board, {file, rank}, moves)] [move_square | _moves(colour, board, {file, rank}, moves)]
true -> true ->
[move_square | _moves(colour, board, {file, rank}, moves)] [move_square | _moves(colour, board, {file, rank}, moves)]
end end
@ -74,7 +66,6 @@ defmodule Chess.Moves.Generator do
piece = piece =
board board
|> Board.piece({file, rank}) |> Board.piece({file, rank})
piece && piece["colour"] == colour piece && piece["colour"] == colour
end end
end end

View File

@ -28,7 +28,7 @@ defmodule Chess.Moves.Piece do
end end
defp attacked_by_knight?(board, {file, rank}) do defp attacked_by_knight?(board, {file, rank}) do
_attacked?(board, {file, rank}, Knight.pattern(), "knight") _attacked?(board, {file, rank}, Knight.pattern, "knight")
end end
defp attacked_by_pawn?(board, {file, rank}) do defp attacked_by_pawn?(board, {file, rank}) do
@ -46,24 +46,22 @@ defmodule Chess.Moves.Piece do
board board
|> Generator.moves({file, rank}, pattern) |> Generator.moves({file, rank}, pattern)
Enum.any?(moves, &match_piece(board, &1, "pawn")) Enum.any?(moves, &(match_piece(board, &1, "pawn")))
end end
defp _attacked?(_board, {0, _rank}, {-1, _}, _), do: false defp _attacked?(_board, {0, _rank}, {-1, _}, _), do: false
defp _attacked?(_board, {_file, 0}, {_, -1}, _), do: false defp _attacked?(_board, {_file, 0}, {_, -1}, _), do: false
defp _attacked?(_board, {7, _rank}, {1, _}, _), do: false defp _attacked?(_board, {7, _rank}, {1, _}, _), do: false
defp _attacked?(_board, {_file, 7}, {_, 1}, _), do: false defp _attacked?(_board, {_file, 7}, {_, 1}, _), do: false
defp _attacked?(board, {file, rank}, {fv, rv}, pieces) do defp _attacked?(board, {file, rank}, {fv, rv}, pieces) do
board board
|> Generator.moves({file, rank}, {fv, rv}) |> Generator.moves({file, rank}, {fv, rv})
|> List.last() |> List.last
|> case do |> case do
{file, rank} -> {file, rank} ->
piece = board["#{file},#{rank}"] piece = board["#{file},#{rank}"]
Enum.any?(pieces, &match?(%{"type" => ^&1}, piece)) Enum.any?(pieces, &(match?(%{"type" => ^&1}, piece)))
nil -> nil ->
false false
end end
@ -74,7 +72,7 @@ defmodule Chess.Moves.Piece do
board board
|> Generator.moves({file, rank}, pattern) |> Generator.moves({file, rank}, pattern)
Enum.any?(moves, &match_piece(board, &1, piece_type)) Enum.any?(moves, &(match_piece(board, &1, piece_type)))
end end
defp match_piece(board, {file, rank}, piece_type) do defp match_piece(board, {file, rank}, piece_type) do

View File

@ -37,10 +37,8 @@ defmodule Chess.Moves.Pieces.Pawn do
cond do cond do
obstruction?(board, {file, rank + 1}) -> obstruction?(board, {file, rank + 1}) ->
[] []
rank == 1 -> rank == 1 ->
[{file, rank + 1} | _moves("white", board, {file, rank + 1})] [{file, rank + 1} | _moves("white", board, {file, rank + 1})]
true -> true ->
[{file, rank + 1}] [{file, rank + 1}]
end end
@ -50,20 +48,16 @@ defmodule Chess.Moves.Pieces.Pawn do
cond do cond do
obstruction?(board, {file, rank - 1}) -> obstruction?(board, {file, rank - 1}) ->
[] []
rank == 6 -> rank == 6 ->
[{file, rank - 1} | _moves("black", board, {file, rank - 1})] [{file, rank - 1} | _moves("black", board, {file, rank - 1})]
true -> true ->
[{file, rank - 1}] [{file, rank - 1}]
end end
end end
def _capture_moves(_colour, _board, {_file, _rank}, []), do: [] def _capture_moves(_colour, _board, {_file, _rank}, []), do: []
def _capture_moves(colour, board, {file, rank}, [{fv, rv} | moves]) do def _capture_moves(colour, board, {file, rank}, [{fv, rv} | moves]) do
move_square = {file + fv, rank + rv} move_square = {file + fv, rank + rv}
if can_capture_piece?(colour, board, move_square) do if can_capture_piece?(colour, board, move_square) do
[move_square | _capture_moves(colour, board, {file, rank}, moves)] [move_square | _capture_moves(colour, board, {file, rank}, moves)]
else else

View File

@ -1,28 +0,0 @@
defmodule Chess.Release do
@moduledoc """
Used for executing DB release tasks when run in production without Mix
installed.
"""
@app :chess
def migrate do
load_app()
for repo <- repos() do
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
end
end
def rollback(repo, version) do
load_app()
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
end
defp repos do
Application.fetch_env!(@app, :ecto_repos)
end
defp load_app do
Application.load(@app)
end
end

View File

@ -23,7 +23,7 @@ defmodule Chess.Repo.Queries do
def opponents(user, query_string) do def opponents(user, query_string) do
user user
|> User.opponents() |> User.opponents
|> User.matches(query_string) |> User.matches(query_string)
end end
end end

View File

@ -8,13 +8,13 @@ defmodule Chess.Store.Move do
alias Chess.Store.Game alias Chess.Store.Game
schema "moves" do schema "moves" do
field(:from, :map) field :from, :map
field(:to, :map) field :to, :map
field(:piece, :map) field :piece, :map
field(:piece_captured, :map) field :piece_captured, :map
belongs_to(:game, Game) belongs_to :game, Game
timestamps() timestamps()
end end
@ -31,7 +31,7 @@ defmodule Chess.Store.Move do
piece: move.piece, piece: move.piece,
piece_captured: move.piece_captured, piece_captured: move.piece_captured,
from: <<97 + move.from["file"], 49 + move.from["rank"]>>, from: <<97 + move.from["file"], 49 + move.from["rank"]>>,
to: <<97 + move.to["file"], 49 + move.to["rank"]>> to: <<97 + move.to["file"], 49 + move.to["rank"]>>,
} }
end end

View File

@ -6,14 +6,16 @@ defmodule Chess.Store.User do
import Ecto.Changeset import Ecto.Changeset
import Ecto.Query import Ecto.Query
schema "users" do alias Comeonin.Argon2
field(:name, :string)
field(:email, :string)
field(:password, :string, virtual: true)
field(:password_hash, :string)
has_many(:games, Chess.Store.Game) schema "users" do
has_many(:games_as_opponent, Chess.Store.Game, foreign_key: :opponent_id) field :name, :string
field :email, :string
field :password, :string, virtual: true
field :password_hash, :string
has_many :games, Chess.Store.Game
has_many :games_as_opponent, Chess.Store.Game, foreign_key: :opponent_id
timestamps() timestamps()
end end
@ -51,32 +53,26 @@ defmodule Chess.Store.User do
end end
def find_by_name(name) do def find_by_name(name) do
from(user in __MODULE__, from user in __MODULE__,
where: user.name == ^name where: user.name == ^name
)
end end
def opponents(user) do def opponents(user) do
from(user in __MODULE__, from user in __MODULE__,
where: user.id != ^user.id where: user.id != ^user.id
)
end end
def matches(query, query_string) do def matches(query, query_string) do
from(user in query, from user in query,
where: where: ilike(user.name, ^"%#{query_string}%")
ilike(user.name, ^"%#{query_string}%") or or user.email == ^query_string
user.email == ^query_string
)
end end
defp hash_password(changeset) do defp hash_password(changeset) do
password = get_change(changeset, :password) password = get_change(changeset, :password)
if password do if password do
changeset changeset
|> change(Argon2.add_hash(password)) |> change(Argon2.add_hash(password))
|> change(password: nil)
else else
changeset changeset
end end

View File

@ -32,9 +32,8 @@ defmodule ChessWeb do
def view do def view do
quote do quote do
use Phoenix.View, use Phoenix.View, root: "lib/chess_web/templates",
root: "lib/chess_web/templates", namespace: ChessWeb
namespace: ChessWeb
# Import convenience functions from controllers # Import convenience functions from controllers
import Phoenix.Controller, import Phoenix.Controller,

View File

@ -68,7 +68,6 @@ defmodule ChessWeb.Presence do
information, while maintaining the required `:metas` field from the information, while maintaining the required `:metas` field from the
original presence data. original presence data.
""" """
use Phoenix.Presence, use Phoenix.Presence, otp_app: :chess,
otp_app: :chess, pubsub_server: Chess.PubSub
pubsub_server: Chess.PubSub
end end

View File

@ -4,7 +4,7 @@ defmodule ChessWeb.UserSocket do
alias Phoenix.Token alias Phoenix.Token
## Channels ## Channels
channel("game:*", ChessWeb.GameChannel) channel "game:*", ChessWeb.GameChannel
# Socket params are passed from the client and can # Socket params are passed from the client and can
# be used to verify and authenticate a user. After # be used to verify and authenticate a user. After
@ -21,12 +21,10 @@ defmodule ChessWeb.UserSocket do
case Token.verify(socket, "game socket", token, max_age: 1_209_600) do case Token.verify(socket, "game socket", token, max_age: 1_209_600) do
{:ok, user_id} -> {:ok, user_id} ->
{:ok, assign(socket, :user_id, user_id)} {:ok, assign(socket, :user_id, user_id)}
{:error, _reason} -> {:error, _reason} ->
:error :error
end end
end end
def connect(%{}, _socket), do: :error def connect(%{}, _socket), do: :error
# Socket id's are topics that allow you to identify all sockets for a given user: # Socket id's are topics that allow you to identify all sockets for a given user:

View File

@ -10,8 +10,8 @@ defmodule ChessWeb.Api.OpponentsController do
conn conn
|> current_user() |> current_user()
|> Queries.opponents(query_string) |> Queries.opponents(query_string)
|> Repo.all() |> Repo.all
render(conn, "index.json", %{opponents: opponents}) render conn, "index.json", %{opponents: opponents}
end end
end end

View File

@ -22,7 +22,6 @@ defmodule ChessWeb.PasswordController do
conn conn
|> put_flash(:info, gettext("Password updated successfully.")) |> put_flash(:info, gettext("Password updated successfully."))
|> redirect(to: page_path(conn, :index)) |> redirect(to: page_path(conn, :index))
{:error, changeset} -> {:error, changeset} ->
render(conn, "edit.html", changeset: changeset) render(conn, "edit.html", changeset: changeset)
end end

View File

@ -22,7 +22,6 @@ defmodule ChessWeb.ProfileController do
conn conn
|> put_flash(:info, gettext("Profile updated successfully.")) |> put_flash(:info, gettext("Profile updated successfully."))
|> redirect(to: page_path(conn, :index)) |> redirect(to: page_path(conn, :index))
{:error, changeset} -> {:error, changeset} ->
render(conn, "edit.html", changeset: changeset) render(conn, "edit.html", changeset: changeset)
end end

View File

@ -18,7 +18,6 @@ defmodule ChessWeb.RegistrationController do
|> Guardian.Plug.sign_in(user) |> Guardian.Plug.sign_in(user)
|> put_flash(:info, "Registered successfully.") |> put_flash(:info, "Registered successfully.")
|> redirect(to: page_path(conn, :index)) |> redirect(to: page_path(conn, :index))
{:error, changeset} -> {:error, changeset} ->
render(conn, "new.html", changeset: changeset) render(conn, "new.html", changeset: changeset)
end end

View File

@ -11,19 +11,17 @@ defmodule ChessWeb.SessionController do
end end
def create( def create(
conn, conn,
%{"user" => %{"email" => email, "password" => password}} %{"user" => %{"email" => email, "password" => password}}
) do ) do
case Auth.authenticate_user(email, password) do case Auth.authenticate_user(email, password) do
{:ok, user} -> {:ok, user} ->
conn conn
|> Guardian.Plug.sign_in(user) |> Guardian.Plug.sign_in(user)
|> put_flash(:info, "You are logged in") |> put_flash(:info, "You are logged in")
|> redirect(to: game_path(conn, :index)) |> redirect(to: game_path(conn, :index))
{:error, _error} -> {:error, _error} ->
changeset = User.changeset(%User{}) changeset = User.changeset(%User{})
conn conn
|> put_flash(:error, "Bad email or password") |> put_flash(:error, "Bad email or password")
|> render("new.html", changeset: changeset) |> render("new.html", changeset: changeset)

View File

@ -7,8 +7,8 @@ defmodule ChessWeb.Endpoint do
signing_salt: "9LqUhZTU" signing_salt: "9LqUhZTU"
] ]
if sandbox = Application.compile_env(:chess, :sandbox) do if Application.get_env(:chess, :sql_sandbox) do
plug(Phoenix.Ecto.SQL.Sandbox, sandbox: sandbox) plug(Phoenix.Ecto.SQL.Sandbox)
end end
socket("/socket", ChessWeb.UserSocket) socket("/socket", ChessWeb.UserSocket)

View File

@ -4,53 +4,57 @@ defmodule ChessWeb.Router do
alias Phoenix.Token alias Phoenix.Token
pipeline :browser do pipeline :browser do
plug(:accepts, ["html"]) plug :accepts, ["html"]
plug(:fetch_session) plug :fetch_session
plug(:fetch_live_flash) plug :fetch_live_flash
plug(:protect_from_forgery) plug :protect_from_forgery
plug(:put_secure_browser_headers) plug :put_secure_browser_headers
end end
pipeline :auth do pipeline :auth do
plug(Chess.Auth.Pipeline) plug Chess.Auth.Pipeline
end end
pipeline :ensure_auth do pipeline :ensure_auth do
plug(Guardian.Plug.EnsureAuthenticated) plug Guardian.Plug.EnsureAuthenticated
plug(:put_user_token) plug :put_user_token
end end
pipeline :api do pipeline :api do
plug(:fetch_session) plug :fetch_session
plug(:accepts, ["json"]) plug :accepts, ["json"]
end end
scope "/", ChessWeb do scope "/", ChessWeb do
# Use the default browser stack pipe_through [:browser, :auth] # Use the default browser stack
pipe_through([:browser, :auth])
get("/", PageController, :index) get "/", PageController, :index
resources("/session", SessionController, only: [:new, :create, :delete], singleton: true) resources "/session", SessionController,
resources("/registration", RegistrationController, only: [:new, :create], singleton: true) only: [:new, :create, :delete], singleton: true
resources "/registration", RegistrationController,
only: [:new, :create], singleton: true
end end
scope "/", ChessWeb do scope "/", ChessWeb do
pipe_through([:browser, :auth, :ensure_auth]) pipe_through [:browser, :auth, :ensure_auth]
resources("/games", GameController, only: [:index, :new, :create, :show, :delete]) resources "/games", GameController,
resources("/profile", ProfileController, only: [:edit, :update], singleton: true) only: [:index, :new, :create, :show, :delete]
resources("/password", PasswordController, only: [:edit, :update], singleton: true) resources "/profile", ProfileController,
only: [:edit, :update], singleton: true
resources "/password", PasswordController,
only: [:edit, :update], singleton: true
end end
# Other scopes may use custom stacks. # Other scopes may use custom stacks.
scope "/api", as: :api do scope "/api", as: :api do
pipe_through([:api, :auth, :ensure_auth]) pipe_through [:api, :auth, :ensure_auth]
resources("/opponents", ChessWeb.Api.OpponentsController, only: [:index]) resources "/opponents", ChessWeb.Api.OpponentsController, only: [:index]
end end
if Mix.env() == :dev do if Mix.env == :dev do
forward("/sent_emails", Bamboo.SentEmailViewerPlug) forward "/sent_emails", Bamboo.SentEmailViewerPlug
end end
defp put_user_token(conn, _) do defp put_user_token(conn, _) do

View File

@ -3,17 +3,16 @@ defmodule ChessWeb.Api.OpponentsView do
def render("index.json", %{opponents: opponents}) do def render("index.json", %{opponents: opponents}) do
%{ %{
opponents: opponents: Enum.map(opponents, fn opponent ->
Enum.map(opponents, fn opponent -> opponent_attrs(opponent)
opponent_attrs(opponent) end)
end)
} }
end end
def opponent_attrs(opponent) do def opponent_attrs(opponent) do
%{ %{
id: opponent.id, id: opponent.id,
name: opponent.name name: opponent.name,
} }
end end
end end

View File

@ -10,7 +10,7 @@ defmodule ChessWeb.ErrorHelpers do
""" """
def error_tag(form, field) do def error_tag(form, field) do
if error = form.errors[field] do if error = form.errors[field] do
content_tag(:span, translate_error(error), class: "help-block") content_tag :span, translate_error(error), class: "help-block"
end end
end end

View File

@ -2,16 +2,16 @@ defmodule ChessWeb.ErrorView do
use ChessWeb, :view use ChessWeb, :view
def render("404.html", _assigns) do def render("404.html", _assigns) do
gettext("Page not found") gettext "Page not found"
end end
def render("500.html", _assigns) do def render("500.html", _assigns) do
gettext("Internal server error") gettext "Internal server error"
end end
# In case no render clause matches or no # In case no render clause matches or no
# template is found, let's render it as 500 # template is found, let's render it as 500
def template_not_found(_template, assigns) do def template_not_found(_template, assigns) do
render("500.html", assigns) render "500.html", assigns
end end
end end

View File

@ -42,8 +42,8 @@ defmodule ChessWeb.GameView do
|> player_colour(game) == game.turn |> player_colour(game) == game.turn
end end
def player_colour(conn, game) do def player_colour(user, game) do
(current_user(conn).id == game.user_id && "white") || "black" (user.id == game.user_id && "white") || "black"
end end
def files(conn, game) do def files(conn, game) do

43
mix.exs
View File

@ -5,9 +5,9 @@ defmodule Chess.Mixfile do
[ [
app: :chess, app: :chess,
version: "0.2.0", version: "0.2.0",
elixir: "~> 1.14.1", elixir: "~> 1.11.3",
elixirc_paths: elixirc_paths(Mix.env()), elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix] ++ Mix.compilers(), compilers: [:phoenix, :gettext] ++ Mix.compilers(),
build_embedded: Mix.env() == :prod, build_embedded: Mix.env() == :prod,
start_permanent: Mix.env() == :prod, start_permanent: Mix.env() == :prod,
aliases: aliases(), aliases: aliases(),
@ -21,7 +21,7 @@ defmodule Chess.Mixfile do
def application do def application do
[ [
mod: {Chess, []}, mod: {Chess, []},
extra_applications: [:logger, :ssl] extra_applications: [:logger]
] ]
end end
@ -34,29 +34,27 @@ defmodule Chess.Mixfile do
# Type `mix help deps` for examples and options. # Type `mix help deps` for examples and options.
defp deps do defp deps do
[ [
{:argon2_elixir, "~> 3.0"}, {:argon2_elixir, "~> 1.3"},
{:bamboo, "~> 2.0"}, {:bamboo, "~> 1.0"},
{:comeonin, "~> 5.0"}, {:comeonin, "~> 4.0"},
{:cowboy, "~> 2.0"}, {:cowboy, "~> 2.1"},
{:plug_cowboy, "~> 2.1"},
{:credo, "~> 1.0", only: [:dev, :test]}, {:credo, "~> 1.0", only: [:dev, :test]},
{:dart_sass, "~> 0.5", runtime: Mix.env() == :dev},
{:ecto_sql, "~> 3.0"}, {:ecto_sql, "~> 3.0"},
{:floki, "~> 0.34", only: :test}, {:floki, ">= 0.27.0", only: :test},
{:esbuild, "~> 0.6", runtime: Mix.env() == :dev}, {:formulator, "~> 0.1.6"},
{:formulator, "~> 0.4.0"}, {:gettext, "~> 0.16.0"},
{:gettext, "~> 0.22.0"}, {:guardian, "~> 1.0"},
{:guardian, "~> 2.0"},
{:jason, "~> 1.0"}, {:jason, "~> 1.0"},
{:phoenix, "~> 1.6.0"}, {:phoenix, "~> 1.5.7"},
{:phoenix_ecto, "~> 4.0"}, {:phoenix_ecto, "~> 4.0"},
{:phoenix_html, "~> 3.2.0"}, {:phoenix_html, "~> 2.0"},
{:phoenix_live_reload, "~> 1.0", only: :dev}, {:phoenix_live_reload, "~> 1.0", only: :dev},
{:phoenix_live_view, "~> 0.18"}, {:phoenix_live_view, "~> 0.15.3"},
{:phoenix_pubsub, "~> 2.0"}, {:phoenix_pubsub, "~> 2.0"},
{:plug_cowboy, "~> 2.0"}, {:postgrex, ">= 0.15.0"},
{:postgrex, "~> 0.16.0"},
{:secure_random, "~> 0.5"}, {:secure_random, "~> 0.5"},
{:wallaby, "~> 0.30.0", [runtime: false, only: :test]} {:wallaby, "~> 0.28.0", [runtime: false, only: :test]}
] ]
end end
@ -70,12 +68,7 @@ defmodule Chess.Mixfile do
[ [
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"], "ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate", "test"], test: ["ecto.create --quiet", "ecto.migrate", "test"]
"assets.deploy": [
"esbuild default --minify",
"sass default --no-source-map --style=compressed",
"phx.digest"
]
] ]
end end
end end

381
mix.lock
View File

@ -1,61 +1,324 @@
%{ %{
"argon2_elixir": {:hex, :argon2_elixir, "3.0.0", "fd4405f593e77b525a5c667282172dd32772d7c4fa58cdecdaae79d2713b6c5f", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "8b753b270af557d51ba13fcdebc0f0ab27a2a6792df72fd5a6cf9cfaffcedc57"}, argon2_elixir:
"bamboo": {:hex, :bamboo, "2.3.0", "d2392a2cabe91edf488553d3c70638b532e8db7b76b84b0a39e3dfe492ffd6fc", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "dd0037e68e108fd04d0e8773921512c940e35d981e097b5793543e3b2f9cd3f6"}, {:hex, :argon2_elixir, "1.3.3",
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "487ffa071ef78c51d9b16e50ff3cf30cf8204e0aa4bdc8afd3765fdd8195e213", [:make, :mix],
"castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"}, [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm",
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "0ca19822ba4b85fe6dab75d1ed36bd9257a88cc4385bc32be177d861a1f3ec31"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, bamboo:
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"}, {:hex, :bamboo, "1.6.0", "adfb583bef028923aae6f22deaea6667290561da1246058556ecaeb0fec5a175",
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, [:mix],
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, [
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, {:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
"credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}
"dart_sass": {:hex, :dart_sass, "0.5.1", "d45f20a8e324313689fb83287d4702352793ce8c9644bc254155d12656ade8b6", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "24f8a1c67e8b5267c51a33cbe6c0b5ebf12c2c83ace88b5ac04947d676b4ec81"}, ], "hexpm", "454e67feacbc9b6e00553ce1d2fba003c861e0035600d59b09d6159985b17f9b"},
"db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"}, bunt:
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38",
"ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"}, [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"ecto_sql": {:hex, :ecto_sql, "3.9.2", "34227501abe92dba10d9c3495ab6770e75e79b836d114c41108a4bf2ce200ad5", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1eb5eeb4358fdbcd42eac11c1fbd87e3affd7904e639d77903c1358b2abd3f70"}, certifi:
"elixir_make": {:hex, :elixir_make, "0.7.3", "c37fdae1b52d2cc51069713a58c2314877c1ad40800a57efb213f77b078a460d", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "24ada3e3996adbed1fa024ca14995ef2ba3d0d17b678b0f3f2b1f66e6ce2b274"}, {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493",
"esbuild": {:hex, :esbuild, "0.6.0", "9ba6ead054abd43cb3d7b14946a0cdd1493698ccd8e054e0e5d6286d7f0f509c", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "30f9a05d4a5bab0d3e37398f312f80864e1ee1a081ca09149d06d474318fd040"}, [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"},
"expo": {:hex, :expo, "0.3.0", "13127c1d5f653b2927f2616a4c9ace5ae372efd67c7c2693b87fd0fdc30c6feb", [:mix], [], "hexpm", "fb3cd4bf012a77bc1608915497dae2ff684a06f0fa633c7afa90c4d72b881823"}, combine:
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f",
"floki": {:hex, :floki, "0.34.0", "002d0cc194b48794d74711731db004fafeb328fe676976f160685262d43706a8", [:mix], [], "hexpm", "9c3a9f43f40dde00332a589bd9d389b90c1f518aef500364d00636acc5ebc99c"}, [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"formulator": {:hex, :formulator, "0.4.0", "43094c3a63e1ee077a01e79425f823d46e031cf7bc9f74045edcda695601efed", [:mix], [{:gettext, ">= 0.11.0", [hex: :gettext, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.4 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "15c34113d6a797bb03d089a0b976b0cf918d64e24d2096986b61735fffaf1980"}, comeonin:
"gettext": {:hex, :gettext, "0.22.0", "a25d71ec21b1848957d9207b81fd61cb25161688d282d58bdafef74c2270bdc4", [:mix], [{:expo, "~> 0.3.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "cb0675141576f73720c8e49b4f0fd3f2c69f0cd8c218202724d4aebab8c70ace"}, {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592",
"guardian": {:hex, :guardian, "2.3.1", "2b2d78dc399a7df182d739ddc0e566d88723299bfac20be36255e2d052fd215d", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "bbe241f9ca1b09fad916ad42d6049d2600bbc688aba5b3c4a6c82592a54274c3"}, [:mix],
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, [
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, {:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0",
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, [hex: :bcrypt_elixir, repo: "hexpm", optional: true]},
"jose": {:hex, :jose, "1.11.5", "3bc2d75ffa5e2c941ca93e5696b54978323191988eb8d225c2e663ddfefd515e", [:mix, :rebar3], [], "hexpm", "dcd3b215bafe02ea7c5b23dafd3eb8062a5cd8f2d904fd9caa323d37034ab384"}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, ], "hexpm", "d8700a0ca4dbb616c22c9b3f6dd539d88deaafec3efe66869d6370c9a559b3e9"},
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"}, connection:
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, {:hex, :connection, "1.1.0",
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm",
"phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"}, "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, cowboy:
"phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d",
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"}, [:rebar3],
"phoenix_live_view": {:hex, :phoenix_live_view, "0.18.11", "c50eac83dae6b5488859180422dfb27b2c609de87f4aa5b9c926ecd0501cd44f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "76c99a0ffb47cd95bf06a917e74f282a603f3e77b00375f3c2dd95110971b102"}, [
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, {:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]},
"phoenix_template": {:hex, :phoenix_template, "1.0.1", "85f79e3ad1b0180abb43f9725973e3b8c2c3354a87245f91431eec60553ed3ef", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "157dc078f6226334c91cb32c1865bf3911686f8bcd6bcff86736f6253e6993ee"}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}
"phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"}, ], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},
"plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"}, cowboy_telemetry:
"plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"}, {:hex, :cowboy_telemetry, "0.3.1",
"plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3],
"poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"}, [
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, {:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]},
"postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, ], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
"secure_random": {:hex, :secure_random, "0.5.1", "c5532b37c89d175c328f5196a0c2a5680b15ebce3e654da37129a9fe40ebf51b", [:mix], [], "hexpm", "1b9754f15e3940a143baafd19da12293f100044df69ea12db5d72878312ae6ab"}, cowlib:
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78",
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"},
"tesla": {:hex, :tesla, "1.5.0", "7ee3616be87024a2b7231ae14474310c9b999c3abb1f4f8dbc70f86bd9678eef", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "1d0385e41fbd76af3961809088aef15dec4c2fdaab97b1c93c6484cb3695a122"}, credo:
"timex": {:hex, :timex, "3.6.3", "58ce6c9eda8ed47fc80c24dde09d481465838d3bcfc230949287fc1b0b0041c1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "6d69f4f95fcf5684102a9cb3cf92c5ba6545bd60ed8d8a6a93cd2a4a4fb0d9ec"}, {:hex, :credo, "1.5.4", "9914180105b438e378e94a844ec3a5088ae5875626fc945b7c1462b41afc3198",
"timex_ecto": {:hex, :timex_ecto, "3.4.0", "7871043345626a591bfa3e313aa271df4a4eda79f51eb69e83f326f0b8f3181c", [:mix], [{:ecto, "~> 2.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:timex, "~> 3.6", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "4237fa971c8fb9baeeb901b3ae4efee663e0da335e291228f215d99cf8a64799"}, [:mix],
"tzdata": {:hex, :tzdata, "1.0.5", "69f1ee029a49afa04ad77801febaf69385f3d3e3d1e4b56b9469025677b89a28", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "55519aa2a99e5d2095c1e61cc74c9be69688f8ab75c27da724eb8279ff402a5a"}, [
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, {:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]},
"wallaby": {:hex, :wallaby, "0.30.1", "81342a34080867ab359aca23de4d1d8c6bbdeb35d8ce2a8c42e42b758d539963", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.2.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "457251df6a94ff80816524136edbce6400cb1ee979586c90224ff634e9543d78"}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]},
"web_driver_client": {:hex, :web_driver_client, "0.2.0", "63b76cd9eb3b0716ec5467a0f8bead73d3d9612e63f7560d21357f03ad86e31a", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "83cc6092bc3e74926d1c8455f0ce927d5d1d36707b74d9a65e38c084aab0350f"}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}
], "hexpm", "cf51af45eadc0a3f39ba13b56fdac415c91b34f7b7533a13dc13550277141bc4"},
db_connection:
{:hex, :db_connection, "2.3.1",
"4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix],
[{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm",
"abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"},
decimal:
{:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697",
[:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
ecto:
{:hex, :ecto, "3.5.5", "48219a991bb86daba6e38a1e64f8cea540cded58950ff38fbc8163e062281a07",
[:mix],
[
{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]},
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
], "hexpm", "98dd0e5e1de7f45beca6130d13116eae675db59adfa055fb79612406acf6f6f1"},
ecto_sql:
{:hex, :ecto_sql, "3.5.3", "1964df0305538364b97cc4661a2bd2b6c89d803e66e5655e4e55ff1571943efd",
[:mix],
[
{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]},
{:ecto, "~> 3.5.0", [hex: :ecto, repo: "hexpm", optional: false]},
{:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]},
{:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]},
{:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]},
{:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}
], "hexpm", "d2f53592432ce17d3978feb8f43e8dc0705e288b0890caf06d449785f018061c"},
elixir_make:
{:hex, :elixir_make, "0.6.2",
"7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm",
"03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
file_system:
{:hex, :file_system, "0.2.10",
"fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm",
"41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
floki:
{:hex, :floki, "0.29.0", "b1710d8c93a2f860dc2d7adc390dd808dc2fb8f78ee562304457b75f4c640881",
[:mix],
[{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}],
"hexpm", "008585ce64b9f74c07d32958ec9866f4b8a124bf4da1e2941b28e41384edaaad"},
formulator:
{:hex, :formulator, "0.1.8",
"eb43e1646828edb6614c2cf9c269d55b3d970414684f1e0290734d22c4936af4", [:mix],
[
{:gettext, ">= 0.11.0", [hex: :gettext, repo: "hexpm", optional: false]},
{:phoenix_html, "~> 2.4", [hex: :phoenix_html, repo: "hexpm", optional: false]}
], "hexpm", "dae3ff05743db0e31ef722e6e6ef7ed32836a65c422979e4c09b7c2f0494cf2c"},
gettext:
{:hex, :gettext, "0.16.1", "e2130b25eebcbe02bb343b119a07ae2c7e28bd4b146c4a154da2ffb2b3507af2",
[:mix], [], "hexpm", "dd3a7ea5e3e87ee9df29452dd9560709b4c7cc8141537d0b070155038d92bdf1"},
guardian:
{:hex, :guardian, "1.2.1", "bdc8dd3dbf0fb7216cb6f91c11831faa1a64d39cdaed9a611e37f2413e584983",
[:mix],
[
{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]},
{:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]},
{:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}
], "hexpm", "723fc404edfb7bd5cba4cd83329b352037f102aa97468f44e58ac7f47c136a98"},
hackney:
{:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c",
[:rebar3],
[
{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]},
{:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]},
{:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]},
{:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]},
{:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]},
{:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]},
{:unicode_util_compat, "~>0.7.0",
[hex: :unicode_util_compat, repo: "hexpm", optional: false]}
], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"},
html_entities:
{:hex, :html_entities, "0.5.1",
"1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm",
"30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
httpoison:
{:hex, :httpoison, "1.8.0",
"6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix],
[{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm",
"28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
idna:
{:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d",
[:rebar3],
[
{:unicode_util_compat, "~>0.7.0",
[hex: :unicode_util_compat, repo: "hexpm", optional: false]}
], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
jason:
{:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052",
[:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}],
"hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
jose:
{:hex, :jose, "1.11.1", "59da64010c69aad6cde2f5b9248b896b84472e99bd18f246085b7b9fe435dcdb",
[:mix, :rebar3], [], "hexpm",
"078f6c9fb3cd2f4cfafc972c814261a7d1e8d2b3685c0a76eb87e158efff1ac5"},
metrics:
{:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486",
[:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
mime:
{:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d",
[:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"},
mimerl:
{:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3",
[:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
parse_trans:
{:hex, :parse_trans, "3.3.1",
"16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm",
"07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
phoenix:
{:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0",
[:mix],
[
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
{:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]},
{:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]},
{:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]},
{:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]},
{:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]},
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"},
phoenix_ecto:
{:hex, :phoenix_ecto, "4.2.1",
"13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix],
[
{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]},
{:phoenix_html, "~> 2.14.2 or ~> 2.15",
[hex: :phoenix_html, repo: "hexpm", optional: true]},
{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}
], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
phoenix_html:
{:hex, :phoenix_html, "2.14.3",
"51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix],
[{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm",
"efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
phoenix_live_reload:
{:hex, :phoenix_live_reload, "1.3.0",
"f35f61c3f959c9a01b36defaa1f0624edd55b87e236b606664a556d6f72fd2e7", [:mix],
[
{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]},
{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}
], "hexpm", "02c1007ae393f2b76ec61c1a869b1e617179877984678babde131d716f95b582"},
phoenix_live_view:
{:hex, :phoenix_live_view, "0.15.3",
"70c7917e5c421e32d1a1c8ddf8123378bb741748cd8091eb9d557fb4be92a94f", [:mix],
[
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]},
{:phoenix, "~> 1.5.7", [hex: :phoenix, repo: "hexpm", optional: false]},
{:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]},
{:telemetry, "~> 0.4.2 or ~> 0.5", [hex: :telemetry, repo: "hexpm", optional: false]}
], "hexpm", "cabcfb6738419a08600009219a5f0d861de97507fc1232121e1d5221aba849bd"},
phoenix_pubsub:
{:hex, :phoenix_pubsub, "2.0.0",
"a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm",
"c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
plug:
{:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e",
[:mix],
[
{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]},
{:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]},
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
plug_cowboy:
{:hex, :plug_cowboy, "2.4.1",
"779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix],
[
{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]},
{:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]},
{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]},
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}
], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
plug_crypto:
{:hex, :plug_crypto, "1.2.0",
"1cb20793aa63a6c619dd18bb33d7a3aa94818e5fd39ad357051a67f26dfa2df6", [:mix], [], "hexpm",
"a48b538ae8bf381ffac344520755f3007cc10bd8e90b240af98ea29b69683fc2"},
poison:
{:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae",
[:mix], [], "hexpm", "ba8836feea4b394bb718a161fc59a288fe0109b5006d6bdf97b6badfcf6f0f25"},
poolboy:
{:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b",
[:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
postgrex:
{:hex, :postgrex, "0.15.7",
"724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix],
[
{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]},
{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]},
{:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]},
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}
], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"},
ranch:
{:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881",
[:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
secure_random:
{:hex, :secure_random, "0.5.1",
"c5532b37c89d175c328f5196a0c2a5680b15ebce3e654da37129a9fe40ebf51b", [:mix], [], "hexpm",
"1b9754f15e3940a143baafd19da12293f100044df69ea12db5d72878312ae6ab"},
ssl_verify_fun:
{:hex, :ssl_verify_fun, "1.1.6",
"cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3],
[], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
telemetry:
{:hex, :telemetry, "0.4.2",
"2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm",
"2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
tesla:
{:hex, :tesla, "1.3.3", "26ae98627af5c406584aa6755ab5fc96315d70d69a24dd7f8369cfcb75094a45",
[:mix],
[
{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]},
{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]},
{:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]},
{:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]},
{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]},
{:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]},
{:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]},
{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]},
{:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]},
{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]},
{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}
], "hexpm", "2648f1c276102f9250299e0b7b57f3071c67827349d9173f34c281756a1b124c"},
timex:
{:hex, :timex, "3.6.3", "58ce6c9eda8ed47fc80c24dde09d481465838d3bcfc230949287fc1b0b0041c1",
[:mix],
[
{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]},
{:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]},
{:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}
], "hexpm", "6d69f4f95fcf5684102a9cb3cf92c5ba6545bd60ed8d8a6a93cd2a4a4fb0d9ec"},
timex_ecto:
{:hex, :timex_ecto, "3.4.0",
"7871043345626a591bfa3e313aa271df4a4eda79f51eb69e83f326f0b8f3181c", [:mix],
[
{:ecto, "~> 2.2", [hex: :ecto, repo: "hexpm", optional: false]},
{:timex, "~> 3.6", [hex: :timex, repo: "hexpm", optional: false]}
], "hexpm", "4237fa971c8fb9baeeb901b3ae4efee663e0da335e291228f215d99cf8a64799"},
tzdata:
{:hex, :tzdata, "1.0.5", "69f1ee029a49afa04ad77801febaf69385f3d3e3d1e4b56b9469025677b89a28",
[:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm",
"55519aa2a99e5d2095c1e61cc74c9be69688f8ab75c27da724eb8279ff402a5a"},
unicode_util_compat:
{:hex, :unicode_util_compat, "0.7.0",
"bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm",
"25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
wallaby:
{:hex, :wallaby, "0.28.0", "2ff217c0f245cadb3e5d91748ebcf0102873ceb9ef8a3507717c8bdd73915668",
[:mix],
[
{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]},
{:httpoison, "~> 0.12 or ~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]},
{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]},
{:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]},
{:web_driver_client, "~> 0.1.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}
], "hexpm", "e58112650d0b51e81714a626eab7d486d7a77342c9bbc2ba262b6653f9b22558"},
web_driver_client:
{:hex, :web_driver_client, "0.1.0",
"19466a989c76b7ec803c796cec0fec4611a64f445fd5120ce50c9e3817e09c2c", [:mix],
[
{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]},
{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]},
{:tesla, "~> 1.3.0", [hex: :tesla, repo: "hexpm", optional: false]}
], "hexpm", "c9c031ca915e8fc75b5e24ac93503244f3cc406dd7f53047087a45aa62d60e9e"}
} }

View File

@ -1,3 +1 @@
node_version=14.15.4 node_version=10.16.0
yarn_version=1.22.10

View File

@ -76,13 +76,15 @@ defmodule Chess.AuthTest do
test "authenticate_user/1 returns false on incorrect password " do test "authenticate_user/1 returns false on incorrect password " do
user_fixture(email: "link@hyrule.com", password: "eyeofsheikah") user_fixture(email: "link@hyrule.com", password: "eyeofsheikah")
assert {:error, message} = Auth.authenticate_user("link@hyrule.com", "shadowtemple") assert {:error, message} =
Auth.authenticate_user("link@hyrule.com", "shadowtemple")
assert message == "invalid password" assert message == "invalid password"
end end
test "authenticate_user/1 returns true on correct password " do test "authenticate_user/1 returns true on correct password " do
user = user_fixture(email: "link@hyrule.com", password: "eyeofsheikah") user = user_fixture(email: "link@hyrule.com", password: "eyeofsheikah")
assert {:ok, ^user} = Auth.authenticate_user("link@hyrule.com", "eyeofsheikah") assert {:ok, ^user} =
Auth.authenticate_user("link@hyrule.com", "eyeofsheikah")
end end
end end
end end

View File

@ -72,7 +72,7 @@ defmodule Chess.BoardTest do
"3,0" => %{"type" => "queen", "colour" => "white"} "3,0" => %{"type" => "queen", "colour" => "white"}
} }
%{board: new_board} = Board.move_piece(board, %{"from" => [3, 0], "to" => [5, 2]}) %{board: new_board} = Board.move_piece(board, %{from: {3, 0}, to: {5, 2}})
assert new_board == %{ assert new_board == %{
"5,2" => %{"type" => "queen", "colour" => "white"} "5,2" => %{"type" => "queen", "colour" => "white"}
@ -85,7 +85,7 @@ defmodule Chess.BoardTest do
"7,0" => %{"type" => "rook", "colour" => "white"} "7,0" => %{"type" => "rook", "colour" => "white"}
} }
%{board: new_board} = Board.move_piece(board, %{"from" => [4, 0], "to" => [6, 0]}) %{board: new_board} = Board.move_piece(board, %{from: {4, 0}, to: {6, 0}})
assert new_board == %{ assert new_board == %{
"6,0" => %{"type" => "king", "colour" => "white"}, "6,0" => %{"type" => "king", "colour" => "white"},
@ -99,7 +99,7 @@ defmodule Chess.BoardTest do
"0,0" => %{"type" => "rook", "colour" => "white"} "0,0" => %{"type" => "rook", "colour" => "white"}
} }
%{board: new_board} = Board.move_piece(board, %{"from" => [4, 0], "to" => [2, 0]}) %{board: new_board} = Board.move_piece(board, %{from: {4, 0}, to: {2, 0}})
assert new_board == %{ assert new_board == %{
"2,0" => %{"type" => "king", "colour" => "white"}, "2,0" => %{"type" => "king", "colour" => "white"},

View File

@ -8,7 +8,7 @@ defmodule Chess.GameStateTest do
test "king is in check" do test "king is in check" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"4,7" => %{"type" => "queen", "colour" => "black"} "4,7" => %{"type" => "queen", "colour" => "black"},
} }
assert GameState.king_in_check?(board, "white") assert GameState.king_in_check?(board, "white")
@ -17,7 +17,7 @@ defmodule Chess.GameStateTest do
test "king is not in check" do test "king is not in check" do
board = %{ board = %{
"5,0" => %{"type" => "king", "colour" => "white"}, "5,0" => %{"type" => "king", "colour" => "white"},
"4,7" => %{"type" => "queen", "colour" => "black"} "4,7" => %{"type" => "queen", "colour" => "black"},
} }
refute GameState.king_in_check?(board, "white") refute GameState.king_in_check?(board, "white")
@ -26,7 +26,7 @@ defmodule Chess.GameStateTest do
test "king is in check by a knight" do test "king is in check by a knight" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"3,2" => %{"type" => "knight", "colour" => "black"} "3,2" => %{"type" => "knight", "colour" => "black"},
} }
assert GameState.king_in_check?(board, "white") assert GameState.king_in_check?(board, "white")
@ -35,7 +35,7 @@ defmodule Chess.GameStateTest do
test "king is in check by a pawn" do test "king is in check by a pawn" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"3,1" => %{"type" => "pawn", "colour" => "black"} "3,1" => %{"type" => "pawn", "colour" => "black"},
} }
assert GameState.king_in_check?(board, "white") assert GameState.king_in_check?(board, "white")
@ -45,7 +45,7 @@ defmodule Chess.GameStateTest do
board = %{ board = %{
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"0,4" => %{"type" => "queen", "colour" => "black"}, "0,4" => %{"type" => "queen", "colour" => "black"},
"1,4" => %{"type" => "rook", "colour" => "black"} "1,4" => %{"type" => "rook", "colour" => "black"},
} }
assert GameState.player_checkmated?(board, "white") assert GameState.player_checkmated?(board, "white")
@ -54,7 +54,7 @@ defmodule Chess.GameStateTest do
test "king is not in checkmate by a queen" do test "king is not in checkmate by a queen" do
board = %{ board = %{
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"0,4" => %{"type" => "queen", "colour" => "black"} "0,4" => %{"type" => "queen", "colour" => "black"},
} }
refute GameState.player_checkmated?(board, "white") refute GameState.player_checkmated?(board, "white")
@ -64,7 +64,7 @@ defmodule Chess.GameStateTest do
board = %{ board = %{
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"1,1" => %{"type" => "queen", "colour" => "black"}, "1,1" => %{"type" => "queen", "colour" => "black"},
"2,3" => %{"type" => "knight", "colour" => "black"} "2,3" => %{"type" => "knight", "colour" => "black"},
} }
assert GameState.player_checkmated?(board, "white") assert GameState.player_checkmated?(board, "white")
@ -75,7 +75,7 @@ defmodule Chess.GameStateTest do
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"2,0" => %{"type" => "knight", "colour" => "white"}, "2,0" => %{"type" => "knight", "colour" => "white"},
"0,5" => %{"type" => "queen", "colour" => "black"}, "0,5" => %{"type" => "queen", "colour" => "black"},
"1,5" => %{"type" => "rook", "colour" => "black"} "1,5" => %{"type" => "rook", "colour" => "black"},
} }
refute GameState.player_checkmated?(board, "white") refute GameState.player_checkmated?(board, "white")
@ -86,7 +86,7 @@ defmodule Chess.GameStateTest do
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"2,3" => %{"type" => "bishop", "colour" => "white"}, "2,3" => %{"type" => "bishop", "colour" => "white"},
"0,5" => %{"type" => "queen", "colour" => "black"}, "0,5" => %{"type" => "queen", "colour" => "black"},
"1,5" => %{"type" => "rook", "colour" => "black"} "1,5" => %{"type" => "rook", "colour" => "black"},
} }
refute GameState.player_checkmated?(board, "white") refute GameState.player_checkmated?(board, "white")
@ -96,7 +96,7 @@ defmodule Chess.GameStateTest do
board = %{ board = %{
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"1,2" => %{"type" => "rook", "colour" => "black"}, "1,2" => %{"type" => "rook", "colour" => "black"},
"2,1" => %{"type" => "rook", "colour" => "black"} "2,1" => %{"type" => "rook", "colour" => "black"},
} }
assert GameState.player_stalemated?(board, "white") assert GameState.player_stalemated?(board, "white")

View File

@ -12,18 +12,18 @@ defmodule Chess.MoveListTest do
%Move{ %Move{
piece: %{"type" => "pawn", "colour" => "white"}, piece: %{"type" => "pawn", "colour" => "white"},
from: %{"file" => 4, "rank" => 1}, from: %{"file" => 4, "rank" => 1},
to: %{"file" => 4, "rank" => 3} to: %{"file" => 4, "rank" => 3},
}, },
%Move{ %Move{
piece: %{"type" => "pawn", "colour" => "black"}, piece: %{"type" => "pawn", "colour" => "black"},
from: %{"file" => 4, "rank" => 6}, from: %{"file" => 4, "rank" => 6},
to: %{"file" => 4, "rank" => 4} to: %{"file" => 4, "rank" => 4},
}, },
%Move{ %Move{
piece: %{"type" => "knight", "colour" => "white"}, piece: %{"type" => "knight", "colour" => "white"},
from: %{"file" => 1, "rank" => 0}, from: %{"file" => 1, "rank" => 0},
to: %{"file" => 2, "rank" => 2} to: %{"file" => 2, "rank" => 2},
} },
] ]
expected_result = [ expected_result = [
@ -51,7 +51,7 @@ defmodule Chess.MoveListTest do
from: "b1", from: "b1",
to: "c3" to: "c3"
} }
] ],
] ]
assert MoveList.transform(moves) == expected_result assert MoveList.transform(moves) == expected_result

View File

@ -6,7 +6,7 @@ defmodule Chess.Moves.PieceTest do
test "piece is not being attacked" do test "piece is not being attacked" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"2,1" => %{"type" => "rook", "colour" => "black"} "2,1" => %{"type" => "rook", "colour" => "black"},
} }
refute Piece.attacked?(board, {4, 5}) refute Piece.attacked?(board, {4, 5})
@ -15,7 +15,7 @@ defmodule Chess.Moves.PieceTest do
test "piece on the edge of the board is not being attacked" do test "piece on the edge of the board is not being attacked" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"2,7" => %{"type" => "rook", "colour" => "black"} "2,7" => %{"type" => "rook", "colour" => "black"},
} }
refute Piece.attacked?(board, {4, 0}) refute Piece.attacked?(board, {4, 0})
@ -25,7 +25,7 @@ defmodule Chess.Moves.PieceTest do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"4,1" => %{"type" => "pawn", "colour" => "white"}, "4,1" => %{"type" => "pawn", "colour" => "white"},
"7,3" => %{"type" => "bishop", "colour" => "black"} "7,3" => %{"type" => "bishop", "colour" => "black"},
} }
assert Piece.attacked?(board, {4, 0}) assert Piece.attacked?(board, {4, 0})
@ -34,7 +34,7 @@ defmodule Chess.Moves.PieceTest do
test "piece is not being attacked by piece of its own colour" do test "piece is not being attacked by piece of its own colour" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"2,5" => %{"type" => "rook", "colour" => "white"} "2,5" => %{"type" => "rook", "colour" => "white"},
} }
refute Piece.attacked?(board, {4, 5}) refute Piece.attacked?(board, {4, 5})
@ -43,7 +43,7 @@ defmodule Chess.Moves.PieceTest do
test "piece can be attacked by a rook" do test "piece can be attacked by a rook" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"2,5" => %{"type" => "rook", "colour" => "black"} "2,5" => %{"type" => "rook", "colour" => "black"},
} }
assert Piece.attacked?(board, {4, 5}) assert Piece.attacked?(board, {4, 5})
@ -52,7 +52,7 @@ defmodule Chess.Moves.PieceTest do
test "piece can be attacked by a bishop" do test "piece can be attacked by a bishop" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"6,7" => %{"type" => "bishop", "colour" => "black"} "6,7" => %{"type" => "bishop", "colour" => "black"},
} }
assert Piece.attacked?(board, {4, 5}) assert Piece.attacked?(board, {4, 5})
@ -61,7 +61,7 @@ defmodule Chess.Moves.PieceTest do
test "piece can be attacked by a queen" do test "piece can be attacked by a queen" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"6,7" => %{"type" => "queen", "colour" => "black"} "6,7" => %{"type" => "queen", "colour" => "black"},
} }
assert Piece.attacked?(board, {4, 5}) assert Piece.attacked?(board, {4, 5})
@ -70,7 +70,7 @@ defmodule Chess.Moves.PieceTest do
test "piece is not attacked by a knight" do test "piece is not attacked by a knight" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"7,7" => %{"type" => "knight", "colour" => "black"} "7,7" => %{"type" => "knight", "colour" => "black"},
} }
refute Piece.attacked?(board, {4, 5}) refute Piece.attacked?(board, {4, 5})
@ -79,7 +79,7 @@ defmodule Chess.Moves.PieceTest do
test "piece can be attacked by a knight" do test "piece can be attacked by a knight" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"5,7" => %{"type" => "knight", "colour" => "black"} "5,7" => %{"type" => "knight", "colour" => "black"},
} }
assert Piece.attacked?(board, {4, 5}) assert Piece.attacked?(board, {4, 5})
@ -88,7 +88,7 @@ defmodule Chess.Moves.PieceTest do
test "piece can be attacked by a pawn" do test "piece can be attacked by a pawn" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"5,6" => %{"type" => "pawn", "colour" => "black"} "5,6" => %{"type" => "pawn", "colour" => "black"},
} }
assert Piece.attacked?(board, {4, 5}) assert Piece.attacked?(board, {4, 5})
@ -97,7 +97,7 @@ defmodule Chess.Moves.PieceTest do
test "piece is not attacked by a pawn directly in front" do test "piece is not attacked by a pawn directly in front" do
board = %{ board = %{
"4,5" => %{"type" => "king", "colour" => "white"}, "4,5" => %{"type" => "king", "colour" => "white"},
"4,6" => %{"type" => "pawn", "colour" => "black"} "4,6" => %{"type" => "pawn", "colour" => "black"},
} }
refute Piece.attacked?(board, {4, 5}) refute Piece.attacked?(board, {4, 5})

View File

@ -7,21 +7,10 @@ defmodule Chess.Moves.Pieces.BishopTest do
board = %{"4,5" => %{"type" => "bishop", "colour" => "white"}} board = %{"4,5" => %{"type" => "bishop", "colour" => "white"}}
moves = Moves.available(board, {4, 5}) moves = Moves.available(board, {4, 5})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {1, 2}, {2, 3}, {3, 4}, {5, 6}, {6, 7},
{0, 1}, {2, 7}, {3, 6}, {5, 4}, {6, 3}, {7, 2},
{1, 2}, ])
{2, 3},
{3, 4},
{5, 6},
{6, 7},
{2, 7},
{3, 6},
{5, 4},
{6, 3},
{7, 2}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -29,60 +18,39 @@ defmodule Chess.Moves.Pieces.BishopTest do
board = %{"0,0" => %{"type" => "bishop", "colour" => "white"}} board = %{"0,0" => %{"type" => "bishop", "colour" => "white"}}
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7},
{1, 1}, ])
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "bishops are blocked by pieces of their own colour" do test "bishops are blocked by pieces of their own colour" do
board = %{ board = %{
"0,0" => %{"type" => "bishop", "colour" => "white"}, "0,0" => %{"type" => "bishop", "colour" => "white"},
"5,5" => %{"type" => "king", "colour" => "white"} "5,5" => %{"type" => "king", "colour" => "white"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {1, 1}, {2, 2}, {3, 3}, {4, 4},
{1, 1}, ])
{2, 2},
{3, 3},
{4, 4}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "bishops can take an opponents piece" do test "bishops can take an opponents piece" do
board = %{ board = %{
"0,0" => %{"type" => "bishop", "colour" => "white"}, "0,0" => %{"type" => "bishop", "colour" => "white"},
"5,5" => %{"type" => "knight", "colour" => "black"} "5,5" => %{"type" => "knight", "colour" => "black"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5},
{1, 1}, ])
{2, 2},
{3, 3},
{4, 4},
{5, 5}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
def board do def board do
Chess.Board.default() Chess.Board.default
end end
end end

View File

@ -7,42 +7,28 @@ defmodule Chess.Moves.Pieces.King.CastlingTest do
test "king can move two spaces to castle with the king side rook" do test "king can move two spaces to castle with the king side rook" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"7,0" => %{"type" => "rook", "colour" => "white"} "7,0" => %{"type" => "rook", "colour" => "white"},
} }
moves = Moves.available(board, {4, 0}) moves = Moves.available(board, {4, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, {6, 0},
{5, 0}, ])
{3, 1},
{4, 1},
{5, 1},
{6, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "king can move two spaces to castle with the queen side rook" do test "king can move two spaces to castle with the queen side rook" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"0,0" => %{"type" => "rook", "colour" => "white"} "0,0" => %{"type" => "rook", "colour" => "white"},
} }
moves = Moves.available(board, {4, 0}) moves = Moves.available(board, {4, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, {2, 0},
{5, 0}, ])
{3, 1},
{4, 1},
{5, 1},
{2, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -50,19 +36,13 @@ defmodule Chess.Moves.Pieces.King.CastlingTest do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"3,0" => %{"type" => "queen", "colour" => "white"}, "3,0" => %{"type" => "queen", "colour" => "white"},
"0,0" => %{"type" => "rook", "colour" => "white"} "0,0" => %{"type" => "rook", "colour" => "white"},
} }
moves = Moves.available(board, {4, 0}) moves = Moves.available(board, {4, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {5, 0}, {3, 1}, {4, 1}, {5, 1},
{5, 0}, ])
{3, 1},
{4, 1},
{5, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -70,20 +50,13 @@ defmodule Chess.Moves.Pieces.King.CastlingTest do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"0,0" => %{"type" => "rook", "colour" => "white"}, "0,0" => %{"type" => "rook", "colour" => "white"},
"2,7" => %{"type" => "queen", "colour" => "black"} "2,7" => %{"type" => "queen", "colour" => "black"},
} }
moves = Moves.available(board, {4, 0}) moves = Moves.available(board, {4, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, ])
{5, 0},
{3, 1},
{4, 1},
{5, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -91,119 +64,88 @@ defmodule Chess.Moves.Pieces.King.CastlingTest do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"0,0" => %{"type" => "rook", "colour" => "white"}, "0,0" => %{"type" => "rook", "colour" => "white"},
"3,7" => %{"type" => "queen", "colour" => "black"} "3,7" => %{"type" => "queen", "colour" => "black"},
} }
moves = Moves.available(board, {4, 0}) moves = Moves.available(board, {4, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, ])
{5, 0},
{3, 1},
{4, 1},
{5, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "cannot castle if the king has moved" do test "cannot castle if the king has moved" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"0,0" => %{"type" => "rook", "colour" => "white"} "0,0" => %{"type" => "rook", "colour" => "white"},
} }
move_list = [ move_list = [
%Move{ %Move{
from: %{"file" => 4, "rank" => 0}, from: %{"file" => 4, "rank" => 0},
to: %{"file" => 4, "rank" => 1}, to: %{"file" => 4, "rank" => 1},
piece: %{"type" => "king", "colour" => "white"} piece: %{"type" => "king", "colour" => "white"}
}, },
%Move{ %Move{
from: %{"file" => 4, "rank" => 1}, from: %{"file" => 4, "rank" => 1},
to: %{"file" => 4, "rank" => 0}, to: %{"file" => 4, "rank" => 0},
piece: %{"type" => "king", "colour" => "white"} piece: %{"type" => "king", "colour" => "white"}
} },
] ]
moves = Moves.available(board, {4, 0}, move_list) moves = Moves.available(board, {4, 0}, move_list)
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, ])
{5, 0},
{3, 1},
{4, 1},
{5, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "cannot castle if the queen side rook has moved" do test "cannot castle if the queen side rook has moved" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"0,0" => %{"type" => "rook", "colour" => "white"} "0,0" => %{"type" => "rook", "colour" => "white"},
} }
move_list = [ move_list = [
%Move{ %Move{
from: %{"file" => 0, "rank" => 0}, from: %{"file" => 0, "rank" => 0},
to: %{"file" => 0, "rank" => 1}, to: %{"file" => 0, "rank" => 1},
piece: %{"type" => "rook", "colour" => "white"} piece: %{"type" => "rook", "colour" => "white"}
}, },
%Move{ %Move{
from: %{"file" => 0, "rank" => 1}, from: %{"file" => 0, "rank" => 1},
to: %{"file" => 0, "rank" => 0}, to: %{"file" => 0, "rank" => 0},
piece: %{"type" => "rook", "colour" => "white"} piece: %{"type" => "rook", "colour" => "white"}
} },
] ]
moves = Moves.available(board, {4, 0}, move_list) moves = Moves.available(board, {4, 0}, move_list)
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, ])
{5, 0},
{3, 1},
{4, 1},
{5, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "cannot castle if the king side rook has moved" do test "cannot castle if the king side rook has moved" do
board = %{ board = %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"7,0" => %{"type" => "rook", "colour" => "white"} "7,0" => %{"type" => "rook", "colour" => "white"},
} }
move_list = [ move_list = [
%Move{ %Move{
from: %{"file" => 7, "rank" => 0}, from: %{"file" => 7, "rank" => 0},
to: %{"file" => 7, "rank" => 1}, to: %{"file" => 7, "rank" => 1},
piece: %{"type" => "rook", "colour" => "white"} piece: %{"type" => "rook", "colour" => "white"}
}, },
%Move{ %Move{
from: %{"file" => 7, "rank" => 1}, from: %{"file" => 7, "rank" => 1},
to: %{"file" => 7, "rank" => 0}, to: %{"file" => 7, "rank" => 0},
piece: %{"type" => "rook", "colour" => "white"} piece: %{"type" => "rook", "colour" => "white"}
} },
] ]
moves = Moves.available(board, {4, 0}, move_list) moves = Moves.available(board, {4, 0}, move_list)
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 0}, {5, 0}, {3, 1}, {4, 1}, {5, 1},
{3, 0}, ])
{5, 0},
{3, 1},
{4, 1},
{5, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
end end

View File

@ -7,18 +7,9 @@ defmodule Chess.Moves.Pieces.KingTest do
board = %{"4,5" => %{"type" => "king", "colour" => "white"}} board = %{"4,5" => %{"type" => "king", "colour" => "white"}}
moves = Moves.available(board, {4, 5}) moves = Moves.available(board, {4, 5})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 4}, {4, 4}, {5, 4}, {5, 5}, {5, 6}, {4, 6}, {3, 6}, {3, 5},
{3, 4}, ])
{4, 4},
{5, 4},
{5, 5},
{5, 6},
{4, 6},
{3, 6},
{3, 5}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -26,34 +17,26 @@ defmodule Chess.Moves.Pieces.KingTest do
board = %{"0,0" => %{"type" => "king", "colour" => "white"}} board = %{"0,0" => %{"type" => "king", "colour" => "white"}}
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {1, 1}, {1, 0},
{0, 1}, ])
{1, 1},
{1, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "kings are blocked by pieces of the same colour" do test "kings are blocked by pieces of the same colour" do
board = %{ board = %{
"0,0" => %{"type" => "king", "colour" => "white"}, "0,0" => %{"type" => "king", "colour" => "white"},
"1,1" => %{"type" => "rook", "colour" => "white"} "1,1" => %{"type" => "rook", "colour" => "white"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {1, 0},
{0, 1}, ])
{1, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
def board do def board do
Chess.Board.default() Chess.Board.default
end end
end end

View File

@ -7,18 +7,9 @@ defmodule Chess.Moves.Pieces.KnightTest do
board = %{"4,5" => %{"type" => "knight", "colour" => "white"}} board = %{"4,5" => %{"type" => "knight", "colour" => "white"}}
moves = Moves.available(board, {4, 5}) moves = Moves.available(board, {4, 5})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {3, 7}, {5, 7}, {6, 6}, {6, 4}, {5, 3}, {3, 3}, {2, 4}, {2, 6},
{3, 7}, ])
{5, 7},
{6, 6},
{6, 4},
{5, 3},
{3, 3},
{2, 4},
{2, 6}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -26,32 +17,26 @@ defmodule Chess.Moves.Pieces.KnightTest do
board = %{"0,0" => %{"type" => "knight", "colour" => "white"}} board = %{"0,0" => %{"type" => "knight", "colour" => "white"}}
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {1, 2}, {2, 1}
{1, 2}, ])
{2, 1}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "knights are blocked by other pieces of the same colour" do test "knights are blocked by other pieces of the same colour" do
board = %{ board = %{
"0,0" => %{"type" => "knight", "colour" => "white"}, "0,0" => %{"type" => "knight", "colour" => "white"},
"1,2" => %{"type" => "king", "colour" => "white"} "1,2" => %{"type" => "king", "colour" => "white"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {2, 1},
{2, 1} ])
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
def board do def board do
Chess.Board.default() Chess.Board.default
end end
end end

View File

@ -36,9 +36,8 @@ defmodule Chess.Moves.Pieces.PawnTest do
test "pawn is blocked from moving two squares by another piece" do test "pawn is blocked from moving two squares by another piece" do
board = %{ board = %{
"4,1" => %{"type" => "pawn", "colour" => "white"}, "4,1" => %{"type" => "pawn", "colour" => "white"},
"4,3" => %{"type" => "pawn", "colour" => "black"} "4,3" => %{"type" => "pawn", "colour" => "black"},
} }
moves = Moves.available(board, {4, 1}) moves = Moves.available(board, {4, 1})
expected_moves = [{4, 2}] expected_moves = [{4, 2}]
@ -48,9 +47,8 @@ defmodule Chess.Moves.Pieces.PawnTest do
test "pawn is blocked from moving one or two squares by another piece" do test "pawn is blocked from moving one or two squares by another piece" do
board = %{ board = %{
"4,1" => %{"type" => "pawn", "colour" => "white"}, "4,1" => %{"type" => "pawn", "colour" => "white"},
"4,2" => %{"type" => "pawn", "colour" => "black"} "4,2" => %{"type" => "pawn", "colour" => "black"},
} }
moves = Moves.available(board, {4, 1}) moves = Moves.available(board, {4, 1})
expected_moves = [] expected_moves = []
@ -60,9 +58,8 @@ defmodule Chess.Moves.Pieces.PawnTest do
test "pawn is blocked from moving one square by another piece" do test "pawn is blocked from moving one square by another piece" do
board = %{ board = %{
"4,2" => %{"type" => "pawn", "colour" => "white"}, "4,2" => %{"type" => "pawn", "colour" => "white"},
"4,3" => %{"type" => "pawn", "colour" => "black"} "4,3" => %{"type" => "pawn", "colour" => "black"},
} }
moves = Moves.available(board, {4, 2}) moves = Moves.available(board, {4, 2})
expected_moves = [] expected_moves = []
@ -72,9 +69,8 @@ defmodule Chess.Moves.Pieces.PawnTest do
test "white pawn can take an opponents piece" do test "white pawn can take an opponents piece" do
board = %{ board = %{
"4,2" => %{"type" => "pawn", "colour" => "white"}, "4,2" => %{"type" => "pawn", "colour" => "white"},
"5,3" => %{"type" => "pawn", "colour" => "black"} "5,3" => %{"type" => "pawn", "colour" => "black"},
} }
moves = Moves.available(board, {4, 2}) moves = Moves.available(board, {4, 2})
expected_moves = [{4, 3}, {5, 3}] expected_moves = [{4, 3}, {5, 3}]
@ -84,9 +80,8 @@ defmodule Chess.Moves.Pieces.PawnTest do
test "black pawn can take an opponents piece" do test "black pawn can take an opponents piece" do
board = %{ board = %{
"6,6" => %{"type" => "pawn", "colour" => "black"}, "6,6" => %{"type" => "pawn", "colour" => "black"},
"5,5" => %{"type" => "pawn", "colour" => "white"} "5,5" => %{"type" => "pawn", "colour" => "white"},
} }
moves = Moves.available(board, {6, 6}) moves = Moves.available(board, {6, 6})
expected_moves = [{6, 5}, {6, 4}, {5, 5}] expected_moves = [{6, 5}, {6, 4}, {5, 5}]
@ -94,6 +89,6 @@ defmodule Chess.Moves.Pieces.PawnTest do
end end
def default_board do def default_board do
Chess.Board.default() Chess.Board.default
end end
end end

View File

@ -7,35 +7,12 @@ defmodule Chess.Moves.Pieces.QueenTest do
board = %{"4,5" => %{"type" => "queen", "colour" => "white"}} board = %{"4,5" => %{"type" => "queen", "colour" => "white"}}
moves = Moves.available(board, {4, 5}) moves = Moves.available(board, {4, 5})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}, {4, 6}, {4, 7},
{4, 0}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {5, 5}, {6, 5}, {7, 5},
{4, 1}, {0, 1}, {1, 2}, {2, 3}, {3, 4}, {5, 6}, {6, 7},
{4, 2}, {2, 7}, {3, 6}, {5, 4}, {6, 3}, {7, 2},
{4, 3}, ])
{4, 4},
{4, 6},
{4, 7},
{0, 5},
{1, 5},
{2, 5},
{3, 5},
{5, 5},
{6, 5},
{7, 5},
{0, 1},
{1, 2},
{2, 3},
{3, 4},
{5, 6},
{6, 7},
{2, 7},
{3, 6},
{5, 4},
{6, 3},
{7, 2}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -43,30 +20,15 @@ defmodule Chess.Moves.Pieces.QueenTest do
board = %{ board = %{
"0,0" => %{"type" => "queen", "colour" => "white"}, "0,0" => %{"type" => "queen", "colour" => "white"},
"0,5" => %{"type" => "king", "colour" => "white"}, "0,5" => %{"type" => "king", "colour" => "white"},
"5,0" => %{"type" => "bishop", "colour" => "white"} "5,0" => %{"type" => "bishop", "colour" => "white"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {0, 2}, {0, 3}, {0, 4},
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0},
{0, 2}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7},
{0, 3}, ])
{0, 4},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -74,36 +36,19 @@ defmodule Chess.Moves.Pieces.QueenTest do
board = %{ board = %{
"0,0" => %{"type" => "queen", "colour" => "white"}, "0,0" => %{"type" => "queen", "colour" => "white"},
"0,5" => %{"type" => "knight", "colour" => "black"}, "0,5" => %{"type" => "knight", "colour" => "black"},
"5,0" => %{"type" => "rook", "colour" => "black"} "5,0" => %{"type" => "rook", "colour" => "black"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5},
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0},
{0, 2}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7},
{0, 3}, ])
{0, 4},
{0, 5},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{5, 0},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
def board do def board do
Chess.Board.default() Chess.Board.default
end end
end end

View File

@ -7,24 +7,10 @@ defmodule Chess.Moves.Pieces.RookTest do
board = %{"4,5" => %{"type" => "rook", "colour" => "white"}} board = %{"4,5" => %{"type" => "rook", "colour" => "white"}}
moves = Moves.available(board, {4, 5}) moves = Moves.available(board, {4, 5})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}, {4, 6}, {4, 7},
{4, 0}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {5, 5}, {6, 5}, {7, 5},
{4, 1}, ])
{4, 2},
{4, 3},
{4, 4},
{4, 6},
{4, 7},
{0, 5},
{1, 5},
{2, 5},
{3, 5},
{5, 5},
{6, 5},
{7, 5}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
@ -32,81 +18,42 @@ defmodule Chess.Moves.Pieces.RookTest do
board = %{"0,0" => %{"type" => "rook", "colour" => "white"}} board = %{"0,0" => %{"type" => "rook", "colour" => "white"}}
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7},
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0},
{0, 2}, ])
{0, 3},
{0, 4},
{0, 5},
{0, 6},
{0, 7},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{5, 0},
{6, 0},
{7, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "rooks are blocked by other pieces of the same colour" do test "rooks are blocked by other pieces of the same colour" do
board = %{ board = %{
"0,0" => %{"type" => "rook", "colour" => "white"}, "0,0" => %{"type" => "rook", "colour" => "white"},
"0,5" => %{"type" => "king", "colour" => "white"} "0,5" => %{"type" => "king", "colour" => "white"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {0, 2}, {0, 3}, {0, 4},
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0},
{0, 2}, ])
{0, 3},
{0, 4},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{5, 0},
{6, 0},
{7, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
test "rooks can take an opponents piece" do test "rooks can take an opponents piece" do
board = %{ board = %{
"0,0" => %{"type" => "rook", "colour" => "white"}, "0,0" => %{"type" => "rook", "colour" => "white"},
"0,5" => %{"type" => "knight", "colour" => "black"} "0,5" => %{"type" => "knight", "colour" => "black"},
} }
moves = Moves.available(board, {0, 0}) moves = Moves.available(board, {0, 0})
expected_moves = expected_moves = Enum.sort([
Enum.sort([ {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5},
{0, 1}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0},
{0, 2}, ])
{0, 3},
{0, 4},
{0, 5},
{1, 0},
{2, 0},
{3, 0},
{4, 0},
{5, 0},
{6, 0},
{7, 0}
])
assert Enum.sort(moves) == expected_moves assert Enum.sort(moves) == expected_moves
end end
def board do def board do
Chess.Board.default() Chess.Board.default
end end
end end

View File

@ -7,59 +7,51 @@ defmodule Chess.Repo.QueriesTest do
describe "opponents" do describe "opponents" do
test "it finds a user on a partial name match" do test "it finds a user on a partial name match" do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
}) opponent = insert(:user, %{
name: "Princess Zelda",
opponent = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganonsucks"
name: "Princess Zelda", })
email: "zelda@hyrule.com",
password: "ganonsucks"
})
result = result =
user user
|> Queries.opponents("zelda") |> Queries.opponents("zelda")
|> Repo.one() |> Repo.one
assert result.id == opponent.id assert result.id == opponent.id
end end
test "it finds a user on a complete email match" do test "it finds a user on a complete email match" do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
}) opponent = insert(:user, %{
name: "Princess Zelda",
opponent = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganonsucks"
name: "Princess Zelda", })
email: "zelda@hyrule.com",
password: "ganonsucks"
})
result = result =
user user
|> Queries.opponents("zelda@hyrule.com") |> Queries.opponents("zelda@hyrule.com")
|> Repo.one() |> Repo.one
assert result.id == opponent.id assert result.id == opponent.id
end end
test "it does not find a user on a partial email" do test "it does not find a user on a partial email" do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
})
insert(:user, %{ insert(:user, %{
name: "Princess Zelda", name: "Princess Zelda",
email: "zelda@hyrule.com", email: "zelda@hyrule.com",
@ -69,7 +61,7 @@ defmodule Chess.Repo.QueriesTest do
result = result =
user user
|> Queries.opponents("hyrule") |> Queries.opponents("hyrule")
|> Repo.one() |> Repo.one
assert result == nil assert result == nil
end end

View File

@ -14,32 +14,29 @@ defmodule Chess.Store.MoveTest do
user = insert(:user) user = insert(:user)
opponent = insert(:opponent) opponent = insert(:opponent)
game = game = insert(:game, %{
insert(:game, %{ board: Board.default,
board: Board.default(), user_id: user.id,
user_id: user.id, opponent_id: opponent.id,
opponent_id: opponent.id })
})
changeset = changeset = Move.changeset(%Move{}, %{
Move.changeset(%Move{}, %{ game_id: game.id,
game_id: game.id, from: %{"file" => 4, "rank" => 1},
from: %{"file" => 4, "rank" => 1}, to: %{"file" => 4, "rank" => 3},
to: %{"file" => 4, "rank" => 3}, piece: %{"type" => "pawn", "colour" => "white"},
piece: %{"type" => "pawn", "colour" => "white"} })
})
assert changeset.valid? assert changeset.valid?
assert {:ok, _move} = Repo.insert(changeset) assert {:ok, _move} = Repo.insert(changeset)
end end
test "move is invalid without a game" do test "move is invalid without a game" do
changeset = changeset = Move.changeset(%Move{}, %{
Move.changeset(%Move{}, %{ from: %{"file" => 4, "rank" => 1},
from: %{"file" => 4, "rank" => 1}, to: %{"file" => 4, "rank" => 3},
to: %{"file" => 4, "rank" => 3}, piece: %{"type" => "pawn", "colour" => "white"},
piece: %{"type" => "pawn", "colour" => "white"} })
})
refute changeset.valid? refute changeset.valid?
end end
@ -48,18 +45,16 @@ defmodule Chess.Store.MoveTest do
user = insert(:user) user = insert(:user)
opponent = insert(:opponent) opponent = insert(:opponent)
game = game = insert(:game, %{
insert(:game, %{ board: Board.default,
board: Board.default(), user_id: user.id,
user_id: user.id, opponent_id: opponent.id,
opponent_id: opponent.id })
})
changeset = changeset = Move.changeset(%Move{}, %{
Move.changeset(%Move{}, %{ game_id: game.id,
game_id: game.id, piece: %{"type" => "pawn", "colour" => "white"},
piece: %{"type" => "pawn", "colour" => "white"} })
})
refute changeset.valid? refute changeset.valid?
end end
@ -68,19 +63,17 @@ defmodule Chess.Store.MoveTest do
user = insert(:user) user = insert(:user)
opponent = insert(:opponent) opponent = insert(:opponent)
game = game = insert(:game, %{
insert(:game, %{ board: Board.default,
board: Board.default(), user_id: user.id,
user_id: user.id, opponent_id: opponent.id,
opponent_id: opponent.id })
})
changeset = changeset = Move.changeset(%Move{}, %{
Move.changeset(%Move{}, %{ game_id: game.id,
game_id: game.id, from: %{"file" => 4, "rank" => 1},
from: %{"file" => 4, "rank" => 1}, to: %{"file" => 4, "rank" => 3},
to: %{"file" => 4, "rank" => 3} })
})
refute changeset.valid? refute changeset.valid?
end end
@ -90,16 +83,16 @@ defmodule Chess.Store.MoveTest do
piece: %{"type" => "pawn", "colour" => "white"}, piece: %{"type" => "pawn", "colour" => "white"},
piece_captured: %{"type" => "pawn", "colour" => "black"}, piece_captured: %{"type" => "pawn", "colour" => "black"},
from: %{"file" => 4, "rank" => 1}, from: %{"file" => 4, "rank" => 1},
to: %{"file" => 4, "rank" => 3} to: %{"file" => 4, "rank" => 3},
} }
assert Move.transform(move) == %{ assert Move.transform(move) == %{
id: nil, id: nil,
piece: %{"type" => "pawn", "colour" => "white"}, piece: %{"type" => "pawn", "colour" => "white"},
piece_captured: %{"type" => "pawn", "colour" => "black"}, piece_captured: %{"type" => "pawn", "colour" => "black"},
from: "e2", from: "e2",
to: "e4" to: "e4"
} }
end end
end end
end end

View File

@ -8,12 +8,10 @@ defmodule ChessWeb.GameChannelTest do
test "assigns game_id to the socket after join" do test "assigns game_id to the socket after join" do
user = insert(:user) user = insert(:user)
game = insert(:game, %{
game = user_id: user.id,
insert(:game, %{ opponent_id: insert(:opponent).id
user_id: user.id, })
opponent_id: insert(:opponent).id
})
token = Phoenix.Token.sign(@endpoint, "game socket", user.id) token = Phoenix.Token.sign(@endpoint, "game socket", user.id)
{:ok, socket} = connect(UserSocket, %{"token" => token}) {:ok, socket} = connect(UserSocket, %{"token" => token})
@ -26,22 +24,20 @@ defmodule ChessWeb.GameChannelTest do
test "returns the game state after join" do test "returns the game state after join" do
user = insert(:user) user = insert(:user)
opponent = insert(:opponent, %{name: "Daruk"}) opponent = insert(:opponent, %{name: "Daruk"})
game = insert(:game, %{
game = user_id: user.id,
insert(:game, %{ opponent_id: opponent.id
user_id: user.id, })
opponent_id: opponent.id
})
token = Phoenix.Token.sign(@endpoint, "game socket", user.id) token = Phoenix.Token.sign(@endpoint, "game socket", user.id)
{:ok, socket} = connect(UserSocket, %{"token" => token}) {:ok, socket} = connect(UserSocket, %{"token" => token})
{:ok, _, _} = subscribe_and_join(socket, "game:#{game.id}", %{}) {:ok, _, _} = subscribe_and_join(socket, "game:#{game.id}", %{})
assert_push("game:update", %{ assert_push "game:update", %{
player: "white", player: "white",
opponent: "Daruk", opponent: "Daruk",
turn: "white" turn: "white",
}) }
end end
end end

View File

@ -2,7 +2,7 @@ defmodule ChessWeb.SessionControllerTest do
use ChessWeb.ConnCase use ChessWeb.ConnCase
test "shows log in form", %{conn: conn} do test "shows log in form", %{conn: conn} do
conn = get(conn, session_path(conn, :new)) conn = get conn, session_path(conn, :new)
assert html_response(conn, 200) =~ "Log in" assert html_response(conn, 200) =~ "Log in"
end end
end end

View File

@ -40,24 +40,22 @@ defmodule Chess.Features.GamesTest do
|> click(button("Create game")) |> click(button("Create game"))
session session
|> assert_has(css(".help-block", text: "can't be blank")) |> assert_has(
css(".help-block", text: "can't be blank")
)
end end
test "can only see own games", %{session: session} do test "can only see own games", %{session: session} do
opponent = opponent = insert(:user, %{
insert(:user, %{ name: "Urbosa",
name: "Urbosa", email: "urbosa@gerudo.town",
email: "urbosa@gerudo.town", password: "gerudoqueen"
password: "gerudoqueen" })
}) user = insert(:user, %{
name: "Zelda",
user = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganonsucks"
name: "Zelda", })
email: "zelda@hyrule.com",
password: "ganonsucks"
})
insert(:game, %{user_id: user.id, opponent_id: opponent.id}) insert(:game, %{user_id: user.id, opponent_id: opponent.id})
session session
@ -74,20 +72,16 @@ defmodule Chess.Features.GamesTest do
end end
test "can see games as an opponent", %{session: session} do test "can see games as an opponent", %{session: session} do
opponent = opponent = insert(:user, %{
insert(:user, %{ name: "Urbosa",
name: "Urbosa", email: "urbosa@gerudo.town",
email: "urbosa@gerudo.town", password: "gerudoqueen"
password: "gerudoqueen" })
}) user = insert(:user, %{
name: "Zelda",
user = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganonsucks"
name: "Zelda", })
email: "zelda@hyrule.com",
password: "ganonsucks"
})
insert(:game, %{user_id: user.id, opponent_id: opponent.id}) insert(:game, %{user_id: user.id, opponent_id: opponent.id})
session session

View File

@ -22,28 +22,27 @@ defmodule Chess.Features.MovesTest do
|> click(link("New game")) |> click(link("New game"))
|> select_opponent("Zelda") |> select_opponent("Zelda")
|> click(button("Create game")) |> click(button("Create game"))
|> click(css("#f4-r1")) |> click(css("#f4-r1"))
|> assert_has(square_selected("f4-r1")) |> assert_has(square_selected("f4-r1"))
|> assert_has(square_containing("f4-r1", %{type: "pawn", colour: "white"})) |> assert_has(square_containing("f4-r1", %{type: "pawn", colour: "white"}))
|> click(css("#f4-r3")) |> click(css("#f4-r3"))
|> assert_has(square_containing("f4-r3", %{type: "pawn", colour: "white"})) |> assert_has(square_containing("f4-r3", %{type: "pawn", colour: "white"}))
|> refute_has(square_containing("f4-r1", %{type: "pawn", colour: "white"})) |> refute_has(square_containing("f4-r1", %{type: "pawn", colour: "white"}))
end end
test "opponents recieves an email on move", %{session: session} do test "opponents recieves an email on move", %{session: session} do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
}) opponent = insert(:user, %{
name: "Zelda",
opponent = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganondorfsucks"
name: "Zelda", })
email: "zelda@hyrule.com",
password: "ganondorfsucks"
})
session session
|> login("link@hyrule.com", "ilovezelda") |> login("link@hyrule.com", "ilovezelda")
@ -89,7 +88,6 @@ defmodule Chess.Features.MovesTest do
email: "link@hyrule.com", email: "link@hyrule.com",
password: "ilovezelda" password: "ilovezelda"
}) })
insert(:user, %{ insert(:user, %{
name: "Zelda", name: "Zelda",
email: "zelda@hyrule.com", email: "zelda@hyrule.com",
@ -103,8 +101,7 @@ defmodule Chess.Features.MovesTest do
|> select_opponent("Zelda") |> select_opponent("Zelda")
|> click(button("Create game")) |> click(button("Create game"))
{:ok, session2} = Wallaby.start_session() {:ok, session2} = Wallaby.start_session
session2 session2
|> login("zelda@hyrule.com", "ganondorfsucks") |> login("zelda@hyrule.com", "ganondorfsucks")
|> click(link("Game with Link")) |> click(link("Game with Link"))
@ -120,7 +117,6 @@ defmodule Chess.Features.MovesTest do
email: "link@hyrule.com", email: "link@hyrule.com",
password: "ilovezelda" password: "ilovezelda"
}) })
insert(:user, %{ insert(:user, %{
name: "Zelda", name: "Zelda",
email: "zelda@hyrule.com", email: "zelda@hyrule.com",
@ -134,8 +130,7 @@ defmodule Chess.Features.MovesTest do
|> select_opponent("Zelda") |> select_opponent("Zelda")
|> click(button("Create game")) |> click(button("Create game"))
{:ok, session2} = Wallaby.start_session() {:ok, session2} = Wallaby.start_session
session2 session2
|> login("zelda@hyrule.com", "ganondorfsucks") |> login("zelda@hyrule.com", "ganondorfsucks")
|> click(link("Game with Link")) |> click(link("Game with Link"))
@ -152,29 +147,25 @@ defmodule Chess.Features.MovesTest do
test "cannot move the king into a position that would result in check", test "cannot move the king into a position that would result in check",
%{session: session} do %{session: session} do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
}) opponent = insert(:user, %{
name: "Zelda",
opponent = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganondorfsucks"
name: "Zelda", })
email: "zelda@hyrule.com",
password: "ganondorfsucks"
})
insert(:game, %{ insert(:game, %{
board: %{ board: %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"3,7" => %{"type" => "queen", "colour" => "black"}, "3,7" => %{"type" => "queen", "colour" => "black"},
"7,7" => %{"type" => "king", "colour" => "black"} "7,7" => %{"type" => "king", "colour" => "black"},
}, },
user_id: user.id, user_id: user.id,
opponent_id: opponent.id, opponent_id: opponent.id,
turn: "white" turn: "white",
}) })
session session
@ -191,30 +182,26 @@ defmodule Chess.Features.MovesTest do
test "cannot make a move that would place the king in check", test "cannot make a move that would place the king in check",
%{session: session} do %{session: session} do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
}) opponent = insert(:user, %{
name: "Zelda",
opponent = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganondorfsucks"
name: "Zelda", })
email: "zelda@hyrule.com",
password: "ganondorfsucks"
})
insert(:game, %{ insert(:game, %{
board: %{ board: %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"4,1" => %{"type" => "rook", "colour" => "white"}, "4,1" => %{"type" => "rook", "colour" => "white"},
"4,7" => %{"type" => "queen", "colour" => "black"}, "4,7" => %{"type" => "queen", "colour" => "black"},
"7,7" => %{"type" => "king", "colour" => "black"} "7,7" => %{"type" => "king", "colour" => "black"},
}, },
user_id: user.id, user_id: user.id,
opponent_id: opponent.id, opponent_id: opponent.id,
turn: "white" turn: "white",
}) })
session session
@ -230,29 +217,25 @@ defmodule Chess.Features.MovesTest do
end end
test "user is informed when the game is in check", %{session: session} do test "user is informed when the game is in check", %{session: session} do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
}) opponent = insert(:user, %{
name: "Zelda",
opponent = email: "zelda@hyrule.com",
insert(:user, %{ password: "ganondorfsucks"
name: "Zelda", })
email: "zelda@hyrule.com",
password: "ganondorfsucks"
})
insert(:game, %{ insert(:game, %{
board: %{ board: %{
"4,0" => %{"type" => "king", "colour" => "white"}, "4,0" => %{"type" => "king", "colour" => "white"},
"3,7" => %{"type" => "queen", "colour" => "black"}, "3,7" => %{"type" => "queen", "colour" => "black"},
"7,7" => %{"type" => "king", "colour" => "black"} "7,7" => %{"type" => "king", "colour" => "black"},
}, },
user_id: user.id, user_id: user.id,
opponent_id: opponent.id, opponent_id: opponent.id,
turn: "black" turn: "black",
}) })
session session

View File

@ -7,12 +7,11 @@ defmodule Chess.Features.PasswordTest do
import Chess.AuthenticationHelpers import Chess.AuthenticationHelpers
test "user can change their password", %{session: session} do test "user can change their password", %{session: session} do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
})
session session
|> login(user.email, "ilovezelda") |> login(user.email, "ilovezelda")
@ -27,12 +26,11 @@ defmodule Chess.Features.PasswordTest do
end end
test "password cannot be blank", %{session: session} do test "password cannot be blank", %{session: session} do
user = user = insert(:user, %{
insert(:user, %{ name: "Link",
name: "Link", email: "link@hyrule.com",
email: "link@hyrule.com", password: "ilovezelda"
password: "ilovezelda" })
})
session session
|> login(user.email, "ilovezelda") |> login(user.email, "ilovezelda")
@ -43,6 +41,8 @@ defmodule Chess.Features.PasswordTest do
|> click(button("Update Password")) |> click(button("Update Password"))
session session
|> assert_has(css("[data-role='password-error']", text: "can't be blank")) |> assert_has(
css("[data-role='password-error']", text: "can't be blank")
)
end end
end end

View File

@ -25,7 +25,9 @@ defmodule Chess.Features.RegistrationTest do
|> click(button("Register")) |> click(button("Register"))
session session
|> assert_has(css("[data-role='name-error']", text: "can't be blank")) |> assert_has(
css("[data-role='name-error']", text: "can't be blank")
)
end end
test "user cannot register without an email", %{session: session} do test "user cannot register without an email", %{session: session} do
@ -37,7 +39,9 @@ defmodule Chess.Features.RegistrationTest do
|> click(button("Register")) |> click(button("Register"))
session session
|> assert_has(css("[data-role='email-error']", text: "can't be blank")) |> assert_has(
css("[data-role='email-error']", text: "can't be blank")
)
end end
test "user cannot register without a password", %{session: session} do test "user cannot register without a password", %{session: session} do
@ -49,6 +53,8 @@ defmodule Chess.Features.RegistrationTest do
|> click(button("Register")) |> click(button("Register"))
session session
|> assert_has(css("[data-role='password-error']", text: "can't be blank")) |> assert_has(
css("[data-role='password-error']", text: "can't be blank")
)
end end
end end

View File

@ -5,7 +5,7 @@ defmodule Chess.FormHelpers do
import Wallaby.Query import Wallaby.Query
def select(session, name, option: option) do def select(session, name, [option: option]) do
session session
|> find(css("[name='#{name}']")) |> find(css("[name='#{name}']"))
|> click(option(option)) |> click(option(option))

View File

@ -18,7 +18,7 @@ defmodule Chess.Factory do
%User{} %User{}
|> User.changeset(params) |> User.changeset(params)
|> Repo.insert!() |> Repo.insert!
end end
def insert(:opponent, new_params) do def insert(:opponent, new_params) do
@ -32,12 +32,12 @@ defmodule Chess.Factory do
%User{} %User{}
|> User.changeset(params) |> User.changeset(params)
|> Repo.insert!() |> Repo.insert!
end end
def insert(:game, params) do def insert(:game, params) do
%Game{} %Game{}
|> Game.changeset(params) |> Game.changeset(params)
|> Repo.insert!() |> Repo.insert!
end end
end end

View File

@ -4,4 +4,4 @@ ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(Chess.Repo, {:shared, self()}) Ecto.Adapters.SQL.Sandbox.mode(Chess.Repo, {:shared, self()})
Application.put_env(:wallaby, :base_url, ChessWeb.Endpoint.url()) Application.put_env(:wallaby, :base_url, ChessWeb.Endpoint.url)

View File

@ -8,16 +8,16 @@ defmodule Chess.ErrorViewTest do
test "renders 404.html" do test "renders 404.html" do
assert render_to_string(ErrorView, "404.html", []) == assert render_to_string(ErrorView, "404.html", []) ==
"Page not found" "Page not found"
end end
test "render 500.html" do test "render 500.html" do
assert render_to_string(ErrorView, "500.html", []) == assert render_to_string(ErrorView, "500.html", []) ==
"Internal server error" "Internal server error"
end end
test "render any other" do test "render any other" do
assert render_to_string(ErrorView, "505.html", []) == assert render_to_string(ErrorView, "505.html", []) ==
"Internal server error" "Internal server error"
end end
end end