Skip to content

Commit 271a67a

Browse files
author
walking dev
authoredSep 10, 2022
tests and initial api (#199)
1 parent 0d9682a commit 271a67a

15 files changed

+288
-49
lines changed
 

‎.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ gitly
44
*.css.map
55
.sass-cache/
66
.lite_workspace.lua
7-
static/assets/version
7+
src/static/assets/version
88
logs/
99
repos/
1010
archives/

‎api/api.v

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module api
2+
3+
struct ApiResponse {
4+
pub:
5+
success bool
6+
}

‎api/branch.v

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module api
2+
3+
pub struct ApiBranchCount {
4+
ApiResponse
5+
pub:
6+
result int
7+
}

‎api/commit.v

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module api
2+
3+
pub struct ApiCommitCount {
4+
ApiResponse
5+
pub:
6+
result int
7+
}

‎api/issue.v

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module api
2+
3+
pub struct ApiIssueCount {
4+
ApiResponse
5+
pub:
6+
result int
7+
}

‎run.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
sassc static/css/gitly.scss > static/css/gitly.css
1+
sassc src/static/css/gitly.scss > src/static/css/gitly.css
22
v .
33
./gitly

‎src/branch_routes.v

+16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
module main
22

33
import vweb
4+
import api
5+
6+
['/api/v1/:user/:repo_name/branches/count']
7+
fn (mut app App) handle_branch_count(username string, repo_name string) vweb.Result {
8+
// TODO: add auth checking module
9+
if !app.exists_user_repo(username, repo_name) {
10+
return app.not_found()
11+
}
12+
13+
count := app.get_count_repo_branches(app.repo.id)
14+
15+
return app.json(api.ApiBranchCount{
16+
success: true
17+
result: count
18+
})
19+
}
420

521
['/:user/:repo/branches']
622
pub fn (mut app App) branches(user string, repo string) vweb.Result {

‎src/commit_routes.v

+16-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,22 @@ module main
33
import vweb
44
import highlight
55
import time
6+
import api
67

7-
['/:user/:repo/:branch_name/commits']
8-
pub fn (mut app App) handle_commits(username string, repo string, branch_name string) vweb.Result {
9-
return app.commits(username, repo, branch_name, 0)
8+
['/api/v1/:user/:repo_name/:branch_name/commits/count']
9+
fn (mut app App) handle_commits_count(username string, repo_name string, branch_name string) vweb.Result {
10+
// TODO: add auth checking module
11+
if !app.exists_user_repo(username, repo_name) {
12+
return app.not_found()
13+
}
14+
15+
branch := app.find_repo_branch_by_name(app.repo.id, branch_name)
16+
count := app.get_repo_commit_count(app.repo.id, branch.id)
17+
18+
return app.json(api.ApiCommitCount{
19+
success: true
20+
result: count
21+
})
1022
}
1123

1224
['/:username/:repo_name/commits/:branch_name/:page']
@@ -18,7 +30,7 @@ pub fn (mut app App) commits(username string, repo_name string, branch_name stri
1830
app.show_menu = true
1931

2032
branch := app.find_repo_branch_by_name(app.repo.id, branch_name)
21-
commits_count := app.get_count_repo_commits(app.repo.id, branch.id)
33+
commits_count := app.get_repo_commit_count(app.repo.id, branch.id)
2234
mut commits := app.find_repo_commits_as_page(app.repo.id, branch.id, page)
2335

2436
// TODO: move to render logic

‎src/commit_service.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn (mut app App) find_repo_commits_as_page(repo_id int, branch_id int, page int)
9898
}
9999
}
100100

101-
fn (mut app App) get_count_repo_commits(repo_id int, branch_id int) int {
101+
fn (mut app App) get_repo_commit_count(repo_id int, branch_id int) int {
102102
return sql app.db {
103103
select count from Commit where repo_id == repo_id && branch_id == branch_id
104104
}

‎src/issue_routes.v

+16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@ module main
22

33
import vweb
44
import validation
5+
import api
6+
7+
['/api/v1/:user/:repo_name/issues/count']
8+
fn (mut app App) handle_issues_count(username string, repo_name string) vweb.Result {
9+
// TODO: add auth checking module
10+
if !app.exists_user_repo(username, repo_name) {
11+
return app.not_found()
12+
}
13+
14+
count := app.get_repo_issue_count(app.repo.id)
15+
16+
return app.json(api.ApiIssueCount{
17+
success: true
18+
result: count
19+
})
20+
}
521

622
['/:user/:repo/issues/new']
723
pub fn (mut app App) new_issue(user string, repo string) vweb.Result {

‎src/issue_service.v

+6
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ fn (mut app App) find_repo_issues_as_page(repo_id int, page int) []Issue {
4545
}
4646
}
4747

48+
fn (mut app App) get_repo_issue_count(repo_id int) int {
49+
return sql app.db {
50+
select count from Issue where repo_id == repo_id
51+
}
52+
}
53+
4854
fn (mut app App) get_all_repo_issues(repo_id int) []Issue {
4955
issues := sql app.db {
5056
select from Issue where repo_id == repo_id && is_pr == false

‎src/repo_routes.v

+6-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pub fn (mut app App) new() vweb.Result {
159159
}
160160

161161
['/new'; post]
162-
pub fn (mut app App) handle_new_repo(name string, clone_url string, description string) vweb.Result {
162+
pub fn (mut app App) handle_new_repo(name string, clone_url string, description string, no_redirect string) vweb.Result {
163163
mut valid_clone_url := clone_url
164164
is_clone_url_empty := validation.is_string_empty(clone_url)
165165
is_public := app.form['repo_visibility'] == 'public'
@@ -245,6 +245,10 @@ pub fn (mut app App) handle_new_repo(name string, clone_url string, description
245245
app.update_repo(mut app.repo)
246246
}
247247

248+
if no_redirect == '1' {
249+
return app.text('ok')
250+
}
251+
248252
has_first_repo_activity := app.has_activity(app.user.id, 'first_repo')
249253

250254
if !has_first_repo_activity {
@@ -354,7 +358,7 @@ pub fn (mut app App) tree(username string, repository_name string, branch_name s
354358
items << dirs
355359
items << files
356360

357-
commits_count := app.get_count_repo_commits(app.repo.id, branch.id)
361+
commits_count := app.get_repo_commit_count(app.repo.id, branch.id)
358362
has_commits := commits_count > 0
359363

360364
// Get readme after updating repository

‎src/repo_template.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn get_declension_form(count int, first_form string, second_form string) string
1212

1313
fn (mut app App) format_commits_count(repo Repo, branch_name string) vweb.RawHtml {
1414
branch := app.find_repo_branch_by_name(repo.id, branch_name)
15-
commits_count := app.get_count_repo_commits(repo.id, branch.id)
15+
commits_count := app.get_repo_commit_count(repo.id, branch.id)
1616

1717
return get_declension_form(commits_count, 'commit', 'commits')
1818
}

‎src/templates/new.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ <h3>New repository</h3>
3636
<input type="radio" id="public" name="repo_visibility" value="public" checked>
3737
<label for="public">Public</label>
3838
</div>
39-
39+
4040
<div>
4141
<input type="radio" id="private" name="repo_visibility" value="private">
4242
<label for="private">Private</label>

‎tests/first_run.v

+196-38
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,83 @@
11
import os
22
import net.http
33
import time
4+
import json
5+
import api
46

5-
const myfolder = os.dir(os.executable())
7+
const gitly_url = 'http://127.0.0.1:8080'
8+
9+
const default_branch = 'main'
10+
11+
const test_username = 'bob'
12+
13+
const test_github_repo_url = 'https://github.com/vlang/ui'
14+
15+
const test_github_repo_primary_branch = 'master'
16+
17+
fn main() {
18+
before()?
19+
20+
test_index_page()
21+
22+
ilog('Register the first user `$test_username`')
23+
mut register_headers, token := register_user(test_username, '1234zxcv', 'bob@example.com') or {
24+
exit_with_message(err.str())
25+
}
26+
27+
ilog('Check all cookies that must be present')
28+
assert register_headers.contains(.set_cookie)
29+
30+
ilog('Ensure the login token is present after registration')
31+
has_token := token != ''
32+
assert has_token
33+
34+
test_user_page(test_username)
35+
test_login_with_token(test_username, token)
36+
test_static_served()
37+
38+
test_create_repo(token, 'test1', '')
39+
assert get_repo_commit_count(token, test_username, 'test1', default_branch) == 0
40+
assert get_repo_issue_count(token, test_username, 'test1') == 0
41+
assert get_repo_branch_count(token, test_username, 'test1') == 0
42+
43+
test_create_repo(token, 'test2', test_github_repo_url)
44+
assert get_repo_commit_count(token, test_username, 'test2', test_github_repo_primary_branch) > 0
45+
assert get_repo_issue_count(token, test_username, 'test2') == 0
46+
assert get_repo_branch_count(token, test_username, 'test2') > 0
47+
48+
after()?
49+
}
50+
51+
fn before() ? {
52+
cd_executable_dir()?
53+
54+
ilog('Make sure gitly is not running')
55+
kill_gitly_processes()
56+
57+
remove_database_if_exists()?
58+
remove_repos_dir_if_exists()?
59+
compile_gitly()
60+
61+
ilog('Start gitly in the background, then wait till gitly starts and is responding to requests')
62+
go run_gitly()
63+
64+
wait_gitly()
65+
}
66+
67+
fn after() ? {
68+
remove_database_if_exists()?
69+
remove_repos_dir_if_exists()?
70+
71+
ilog('Ensure gitly is stopped')
72+
kill_gitly_processes()
73+
}
74+
75+
fn run_gitly() {
76+
gitly_process := os.execute('./gitly &')
77+
if gitly_process.exit_code != 0 {
78+
exit_with_message(gitly_process.str())
79+
}
80+
}
681

782
[noreturn]
883
fn exit_with_message(message string) {
@@ -14,33 +89,56 @@ fn ilog(message string) {
1489
println('$time.now().format_ss_milli() | $message')
1590
}
1691

17-
fn main() {
92+
fn cd_executable_dir() ? {
93+
executable_dir := os.dir(os.executable())
1894
// Ensure that we are always running in the gitly folder, no matter what is the starting one:
19-
os.chdir(os.dir(myfolder))?
95+
os.chdir(os.dir(executable_dir))?
96+
2097
ilog('Testing first gitly run.')
98+
}
2199

22-
ilog('Make sure gitly is not running')
100+
fn kill_gitly_processes() {
23101
os.execute('pkill -9 gitly')
102+
}
24103

104+
fn remove_database_if_exists() ? {
25105
ilog('Remove old gitly DB')
106+
26107
if os.exists('gitly.sqlite') {
27108
os.rm('gitly.sqlite')?
28109
}
110+
}
111+
112+
fn remove_repos_dir_if_exists() ? {
113+
ilog('Remove repos directory')
114+
115+
if os.exists('repos') {
116+
os.rmdir_all('repos')?
117+
}
118+
}
29119

120+
fn compile_gitly() {
30121
ilog('Compile gitly')
122+
31123
os.execute('v .')
124+
}
32125

33-
ilog('Start gitly in the background, then wait till gitly starts and is responding to requests')
34-
go run_gitly()
126+
fn wait_gitly() {
35127
for waiting_cycles := 0; waiting_cycles < 50; waiting_cycles++ {
36-
ilog(' wait: $waiting_cycles')
128+
ilog('\twait: $waiting_cycles')
37129
time.sleep(100 * time.millisecond)
38-
http.get('http://127.0.0.1:8080') or { continue }
130+
http.get(prepare_url('')) or { continue }
39131
break
40132
}
133+
}
41134

135+
fn prepare_url(path string) string {
136+
return '$gitly_url/$path'
137+
}
138+
139+
fn test_index_page() {
42140
ilog("Ensure gitly's main page is up")
43-
index_page_result := http.get('http://127.0.0.1:8080') or { exit_with_message(err.str()) }
141+
index_page_result := http.get(prepare_url('')) or { exit_with_message(err.str()) }
44142
assert index_page_result.body.contains('<html>')
45143
assert index_page_result.body.contains('</html>')
46144

@@ -51,56 +149,116 @@ fn main() {
51149

52150
// Make sure no one's logged in
53151
assert index_page_result.body.contains("<a href='/login' class='login-button'>Log in</a>")
152+
}
54153

55-
ilog('Register the first user `bob`')
56-
mut register_result := http.post('http://127.0.0.1:8080/register', 'username=bob&password=1234zxcv&email=bob@example.com&no_redirect=1') or {
57-
exit_with_message(err.str())
154+
// returns headers and token
155+
fn register_user(username string, password string, email string) ?(http.Header, string) {
156+
response := http.post(prepare_url('register'), 'username=$username&password=$password&email=$email&no_redirect=1') or {
157+
return err
58158
}
59-
ilog('Check all cookies that must be present')
60-
assert register_result.header.contains(.set_cookie)
61159

62-
ilog('Ensure the login token is present after registration')
63-
mut has_token := false
64160
mut token := ''
65-
for val in register_result.header.values(.set_cookie) {
161+
for val in response.header.values(.set_cookie) {
66162
token = val.find_between('token=', ';')
67-
has_token = token != ''
68163
}
69-
assert has_token
70164

71-
ilog('Testing the new user /bob page is up after registration')
72-
user_page_result := http.get('http://127.0.0.1:8080/bob') or { exit_with_message(err.str()) }
73-
assert user_page_result.body.contains('<h3>bob</h3>')
165+
return response.header, token
166+
}
167+
168+
fn test_static_served() {
169+
ilog('Ensure that static css is served')
170+
css := http.get(prepare_url('css/gitly.css')) or { exit_with_message(err.str()) }
171+
172+
assert css.status_code != 404
173+
assert css.body.contains('body')
174+
assert css.body.contains('html')
175+
}
176+
177+
fn test_user_page(username string) {
178+
ilog('Testing the new user /$username page is up after registration')
179+
user_page_result := http.get(prepare_url(username)) or { exit_with_message(err.str()) }
180+
181+
assert user_page_result.body.contains('<h3>$username</h3>')
182+
}
183+
184+
fn test_login_with_token(username string, token string) {
185+
ilog('Try to login in with `$username` user token')
74186

75-
ilog('Try to login in with `bob` user token')
76187
login_result := http.fetch(
77188
method: .get
78189
cookies: {
79190
'token': token
80191
}
81-
url: 'http://127.0.0.1:8080/bob'
192+
url: prepare_url(username)
82193
) or { exit_with_message(err.str()) }
83194

84-
ilog('Ensure that after login, there is a signed in as `bob` message')
195+
ilog('Ensure that after login, there is a signed in as `$username` message')
196+
85197
assert login_result.body.contains('<span>Signed in as</span>')
86-
assert login_result.body.contains("<a href='/bob'>bob</a>")
198+
assert login_result.body.contains("<a href='/$username'>$username</a>")
199+
}
87200

88-
ilog('Ensure that static css is served')
89-
css := http.get('http://127.0.0.1:8080/css/gitly.css') or { exit_with_message(err.str()) }
201+
fn test_create_repo(token string, name string, clone_url string) {
202+
description := 'test description'
203+
repo_visibility := 'public'
90204

91-
println(css)
205+
response := http.fetch(
206+
method: .post
207+
cookies: {
208+
'token': token
209+
}
210+
url: prepare_url('new')
211+
data: 'name=$name&description=$description&clone_url=$clone_url&repo_visibility=$repo_visibility&no_redirect=1'
212+
) or { exit_with_message(err.str()) }
92213

93-
assert css.status_code != 404
94-
assert css.body.contains('body')
95-
assert css.body.contains('html')
214+
assert response.status_code == 200
215+
assert response.body == 'ok'
216+
}
96217

97-
ilog('Ensure gitly is stopped')
98-
os.execute('pkill -9 gitly')
218+
fn get_repo_commit_count(token string, username string, repo_name string, branch_name string) int {
219+
response := http.fetch(
220+
method: .get
221+
cookies: {
222+
'token': token
223+
}
224+
url: prepare_url('api/v1/$username/$repo_name/$branch_name/commits/count')
225+
) or { exit_with_message(err.str()) }
226+
227+
response_json := json.decode(api.ApiCommitCount, response.body) or {
228+
exit_with_message(err.str())
229+
}
230+
231+
return response_json.result
99232
}
100233

101-
fn run_gitly() {
102-
gitly_process := os.execute('./gitly &')
103-
if gitly_process.exit_code != 0 {
104-
exit_with_message(gitly_process.str())
234+
fn get_repo_issue_count(token string, username string, repo_name string) int {
235+
response := http.fetch(
236+
method: .get
237+
cookies: {
238+
'token': token
239+
}
240+
url: prepare_url('api/v1/$username/$repo_name/issues/count')
241+
) or { exit_with_message(err.str()) }
242+
243+
response_json := json.decode(api.ApiIssueCount, response.body) or {
244+
exit_with_message(err.str())
105245
}
246+
247+
return response_json.result
248+
}
249+
250+
fn get_repo_branch_count(token string, username string, repo_name string) int {
251+
response := http.fetch(
252+
method: .get
253+
cookies: {
254+
'token': token
255+
}
256+
url: prepare_url('api/v1/$username/$repo_name/branches/count')
257+
) or { exit_with_message(err.str()) }
258+
259+
response_json := json.decode(api.ApiBranchCount, response.body) or {
260+
exit_with_message(err.str())
261+
}
262+
263+
return response_json.result
106264
}

0 commit comments

Comments
 (0)
Please sign in to comment.