Add API integration tests

This commit is contained in:
Pig Fang 2019-04-27 13:09:10 +08:00
parent 51e4efba7b
commit 25256b0814
13 changed files with 1709 additions and 4 deletions

View File

@ -75,6 +75,23 @@ jobs:
- run: touch storage/testing.sqlite
- run: ./vendor/bin/phpunit
api_test:
working_directory: ~/repo
docker:
- image: blessingskin/ci:rust
steps:
- attach_workspace:
at: ~/repo
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Cargo.lock" }}
- v1-dependencies-
- run: ./scripts/api-test.sh
- save_cache:
paths:
- target
key: v1-dependencies-{{ checksum "Cargo.lock" }}
workflows:
version: 2
install_and_test:
@ -90,3 +107,6 @@ workflows:
- php7.3:
requires:
- composer
- api_test:
requires:
- composer

View File

@ -9,5 +9,5 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{php,md,tpl}]
[*.{php,md,tpl,rs}]
indent_size = 4

1
.gitignore vendored
View File

@ -9,6 +9,7 @@ vendor/*
storage/textures/*
storage/update_cache/*
node_modules/*
target/
yarn-error.log
_ide_helper.php
.phpstorm.meta.php

1475
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "test"
version = "0.1.0"
authors = ["Pig Fang <g-plane@hotmail.com>"]
edition = "2018"
[lib]
path = "tests/Api/tests/main.rs"
doctest = false
[dev-dependencies]
reqwest = "0.9"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

View File

@ -19,7 +19,9 @@ class ExecuteInstallation extends Command
return;
}
$this->call('key:random');
if (config('app.env') != 'testing') {
$this->call('key:random');
}
$this->call('salt:random');
$this->call('migrate', ['--force' => true]);
$this->call('jwt:secret', ['--no-interaction' => true]);

View File

@ -36,7 +36,6 @@ class Kernel extends HttpKernel
],
'api' => [
'throttle:60,1',
'bindings',
],

View File

@ -111,7 +111,9 @@ class RouteServiceProvider extends ServiceProvider
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->middleware(
config('app.env') == 'testing' ? ['api'] : ['api', 'throttle:60,1']
)
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}

15
scripts/api-test.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
export APP_ENV="testing"
export DB_CONNECTION="sqlite"
export DB_DATABASE="/tmp/test.db"
if [ -e $DB_DATABASE ]; then rm $DB_DATABASE; fi;
touch $DB_DATABASE
if [ ! -e .env ]; then cp .env.testing .env ; fi;
php artisan bs:install ibara.mayaka@api.test 12345678 hyouka --quiet
php artisan serve --port 32123 --quiet &
cargo test -- --test-threads=1
kill $(ps -ef | grep 'php artisan serve' | awk '{print $2}' | awk -F"/" '{print $1}' | head -n 1)
kill $(ps -ef | grep 'php -S' | awk '{print $2}' | awk -F"/" '{print $1}' | head -n 1)

66
tests/Api/tests/auth.rs Normal file
View File

@ -0,0 +1,66 @@
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize)]
struct Token {
token: String,
}
pub fn login() -> String {
let client = reqwest::Client::new();
let mut response = client
.post("http://127.0.0.1:32123/api/auth/login")
.json(&json!({
"email": "ibara.mayaka@api.test",
"password": "12345678"
}))
.send()
.unwrap();
let Token { token } = response.json().unwrap();
format!("Bearer {}", token)
}
#[test]
fn successful_login() {
assert_ne!(login(), "Bearer ".to_string());
}
#[test]
fn failed_login() {
let client = reqwest::Client::new();
let mut response = client
.post("http://127.0.0.1:32123/api/auth/login")
.json(&json!({
"email": "ibara.mayaka@api.test",
"password": "wrong-password"
}))
.send()
.unwrap();
let Token { token } = response.json().unwrap();
assert_eq!(token, "".to_string());
}
#[test]
fn logout() {
let token = login();
let client = reqwest::Client::new();
let response = client
.post("http://127.0.0.1:32123/api/auth/logout")
.header("Authorization", token)
.send()
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::NO_CONTENT);
}
#[test]
fn refresh_token() {
let token = login();
let client = reqwest::Client::new();
let mut response = client
.post("http://127.0.0.1:32123/api/auth/refresh")
.header("Authorization", token.clone())
.send()
.unwrap();
let Token { token: new_token } = response.json().unwrap();
assert_ne!(token, new_token);
}

8
tests/Api/tests/main.rs Normal file
View File

@ -0,0 +1,8 @@
#[cfg(test)]
mod types;
#[cfg(test)]
mod auth;
#[cfg(test)]
mod players;

View File

@ -0,0 +1,86 @@
use crate::auth::login;
use crate::types::JsonBody;
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize)]
struct Player {
pub pid: u32,
pub name: String,
pub tid_skin: u32,
pub tid_cape: u32,
}
#[test]
fn create_player() {
let client = reqwest::Client::new();
let body = client
.post("http://127.0.0.1:32123/api/players")
.header("Authorization", login())
.json(&json!({"name": "kotenbu_member"}))
.send()
.unwrap()
.json::<JsonBody<Player>>()
.unwrap();
assert!(body.is_success());
}
#[test]
fn get_all_players() {
let client = reqwest::Client::new();
let body = client
.get("http://127.0.0.1:32123/api/players")
.header("Authorization", login())
.send()
.unwrap()
.json::<JsonBody<Vec<Player>>>()
.unwrap();
assert!(body.is_success());
let players = body.data().unwrap();
assert_eq!(players.len(), 1);
let player = players.get(0).unwrap();
assert_eq!(player.pid, 1);
assert_eq!(player.name, String::from("kotenbu_member"));
assert_eq!(player.tid_skin, 0);
assert_eq!(player.tid_cape, 0);
}
#[test]
fn modify_player_name() {
let client = reqwest::Client::new();
let body = client
.put("http://127.0.0.1:32123/api/players/1/name")
.header("Authorization", login())
.json(&json!({"name": "kotenbu"}))
.send()
.unwrap()
.json::<JsonBody<Player>>()
.unwrap();
assert!(body.is_success());
let player = body.data().unwrap();
assert_eq!(player.name, String::from("kotenbu"));
}
#[test]
fn remove_player() {
let client = reqwest::Client::new();
let body = client
.delete("http://127.0.0.1:32123/api/players/1")
.header("Authorization", login())
.send()
.unwrap()
.json::<JsonBody<Player>>()
.unwrap();
assert!(body.is_success());
let body = client
.get("http://127.0.0.1:32123/api/players")
.header("Authorization", login())
.send()
.unwrap()
.json::<JsonBody<Vec<Player>>>()
.unwrap();
assert_eq!(body.data().unwrap().len(), 0);
}

17
tests/Api/tests/types.rs Normal file
View File

@ -0,0 +1,17 @@
use serde::Deserialize;
#[derive(Deserialize)]
pub struct JsonBody<T> {
code: u8,
data: Option<T>,
}
impl<T> JsonBody<T> {
pub fn is_success(&self) -> bool {
self.code == 0
}
pub fn data(self) -> Option<T> {
self.data
}
}