ref: 1b4520b8cf130ca34181064c5876cee2479dd9ea
parent: 4ca7a9ce4fe13f3561f09e9166aa9461e2be50e4
parent: c538333e4fb36451e119595cccc7cdde9ffefa16
author: Michael Misch <michaelmisch1985@gmail.com>
date: Tue Mar 31 04:50:10 PDT 2020
Merge pull request #7 from olmaxmedical/testing Add tests/modifications
--- a/doctor/application.go
+++ b/doctor/application.go
@@ -24,44 +24,56 @@
func application(r *http.Request, p *message.Printer) []string {
var errors []string
- data, err := forms.Parse(r)
+ data, err := forms.ParseMax(r, r.ContentLength)
if err != nil {
- errors = append(errors, fmt.Sprintf("Internal server error %v", err))
+ errors = append(errors, fmt.Sprintf("validation error %v", err))
return errors
}
+
val := data.Validator()
val.Require("gender").Message(p.Sprint("Please select a biological gender"))
+
if r.PostFormValue("gender") != "male" && r.PostFormValue("gender") != "female" {
val.AddError("gender", p.Sprint("Invalid selection for gender"))
}
+
val.RequireFile("cv").Message(p.Sprint("Empty or missing CV"))
- val.AcceptFileExts("cv", "application/msword,applicationvnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf").Message(p.Sprint("Unsupported filetype for CV"))
+ val.AcceptFileExts("cv", "application/msword,applicationvnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf").Message(p.Sprint("unsupported filetype for cv"))
val.RequireFile("diploma").Message(p.Sprint("Empty or missing Diploma/Board Certification"))
- val.AcceptFileExts("cv", "application/msword,applicationvnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf").Message(p.Sprint("Unsupported filetype for Diploma/Board Certification"))
+ val.AcceptFileExts("diploma", "application/msword,applicationvnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf").Message(p.Sprint("unsupported filetype for diploma"))
+
for i := 1; i < 12; i++ {
num := fmt.Sprintf("q%d", i)
+
sel, ok := r.Form[num]
if !ok {
val.AddError(num, p.Sprintf("No selection for question %d", i))
continue
}
+
if sel[0] == "Yes" || sel[0] == "yes" || sel[0] == "no" || sel[0] == "No" {
continue
}
+
val.AddError(num, p.Sprintf("Invalid selection for question %d", i))
}
+
val.Require("email").Message(p.Sprintf("Valid email required"))
val.MatchEmail("email").Message(p.Sprintf("Invalid email"))
val.Require("name").Message(p.Sprintf("Full name required"))
val.MinLength("name", 2).Message(p.Sprintf("Full name must be at least 2 characters"))
+
if r.PostFormValue("redFlag") != "on" {
val.AddError("redFlag", p.Sprint("Invalid selection for confirm element"))
}
+
if val.HasErrors() {
errors = append(errors, val.Messages()...)
}
+
r.Form["pagetitle"] = []string{"Application for doctor"}
r.Form["sendto"] = []string{"olmaxmedical@gmail.com"}
delete(r.Form, "redFlag")
+
return errors
}
--- a/doctor/application_test.go
+++ b/doctor/application_test.go
@@ -1,125 +1,94 @@
package forms
import (
- "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "mime/multipart"
"net/http"
- "strings"
"testing"
+
+ "github.com/olmaxmedical/forms/util"
+ "golang.org/x/text/message"
)
-// This isn't quite right yet, we'll get a working test soon.
-var req = `POST /doctor/application.html HTTP/1.1
-Host: localhost
-User-Agent: Mozilla/5.0
-Accept: */*
-Connection: keep-alive
-Cache-Control: no-cache
-Content-Length: 2028
-Content-Type: multipart/form-data; boundary=--------------------
+func TestApplication(t *testing.T) {
+ fields := map[string]string{
+ "qs": "no",
+ "gender": "male",
+ "email": "foo@bar.ca",
+ "name": "Doctor Octopus",
+ "redFlag": "on",
+ }
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="Specialty"
+ if e := testApplication(t, fields); e != nil {
+ t.Error(e)
+ }
-bariatric
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="country"
+ fields["gender"] = "pineapple"
+ if e := testApplication(t, fields); e == nil {
+ t.Error("invalid field accepted")
+ }
-Albania
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="email"
+ fields["gender"] = "male"
+ fields["email"] = "foo@bar@ca"
+ if e := testApplication(t, fields); e == nil {
+ t.Error("invalid field accepted")
+ }
-mee%40foo.ca
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="gender"
+ fields["email"] = "foo@bar.ca"
+ fields["qs"] = "true"
+ if e := testApplication(t, fields); e == nil {
+ t.Error("invalid field accepted")
+ }
+}
-male
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="name"
+func testApplication(t *testing.T, fields map[string]string) error {
+ var reqBody bytes.Buffer
-mememe
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="pagetitle"
+ mpw := multipart.NewWriter(&reqBody)
+ files := map[string]string{
+ "cv": "resume.pdf",
+ "diploma": "certificate.pdf",
+ }
-Application+for+doctor
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q1"
+ for key, value := range files {
+ if e := util.WriteFile(mpw, key, "../resources/"+value); e != nil {
+ panic(e)
+ }
+ }
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q10"
+ for key, value := range fields {
+ if key == "qs" {
+ for i := 0; i < 12; i++ {
+ key = fmt.Sprintf("q%d", i)
+ if e := mpw.WriteField(key, value); e != nil {
+ panic(e)
+ }
+ }
+ continue
+ }
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q11"
+ if e := mpw.WriteField(key, value); e != nil {
+ panic(e)
+ }
+ }
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q2"
+ request := util.BuildMultiRequest(mpw, &reqBody)
+ printer := message.NewPrinter(message.MatchLanguage("en"))
+ return runTest(request, printer)
+}
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q3"
+func runTest(request *http.Request, printer *message.Printer) error {
+ for _, err := range application(request, printer) {
+ switch err {
+ case "unsupported filetype for cv":
+ case "unsupported filetype for diploma":
+ default:
+ return errors.New(err)
+ }
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q4"
-
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q5"
-
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q6"
-
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q7"
-
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q8"
-
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="q9"
-
-No
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="sendto"
-
-olmaxmedical%40gmail.com
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="cv"
-
-resume.pdf
---------------------------4ee5f9ad0b2d7899
-Content-Disposition: form-data; name="form"
-
-resume.pdf
---------------------------4ee5f9ad0b2d7899`
-
-func TestApplication(t *testing.T) {
- // Build a POST request with a map of entries
- rd := bufio.NewReader(strings.NewReader(req))
-
- request, err := http.ReadRequest(rd)
- if err != nil {
- t.Errorf("test design error: bad request: %v", err)
- return
}
- if e := request.ParseMultipartForm(request.ContentLength); e != nil {
- t.Error(e)
- }
- /*
- printer := message.NewPrinter(message.MatchLanguage("en"))
-
- resp := application(request, printer)
- if len(resp) > 0 {
- for _, err := range resp {
- t.Errorf("%s", err)
- }
- }
- */
+ return nil
}
--- a/doctor/profile.go
+++ b/doctor/profile.go
@@ -23,7 +23,7 @@
func profile(r *http.Request, p *message.Printer) []string {
var errors []string
- data, err := forms.Parse(r)
+ data, err := forms.ParseMax(r, r.ContentLength)
if err != nil {
errors = append(errors, "Internal server error")
return errors
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@
go 1.14
require (
- github.com/albrow/forms v0.3.3
+ github.com/albrow/forms v0.3.4-0.20170215231405-c4277021bca2
github.com/olmaxmedical/plugins v0.0.1
github.com/olmaxmedical/router v0.0.1
golang.org/x/text v0.3.2
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-github.com/albrow/forms v0.3.3 h1:+40fCsDyS2lU97IEeed7bnUGENvlVzppQGBGy6kd77E=
-github.com/albrow/forms v0.3.3/go.mod h1:jvrM3b0gPuIRiY1E/KmKfPk2XXDEKj7yFB+g9g0BItQ=
+github.com/albrow/forms v0.3.4-0.20170215231405-c4277021bca2 h1:SnKbJhjY6YOX6cC0JL19DzxJ4nMZoTFqRJ006tgpclw=
+github.com/albrow/forms v0.3.4-0.20170215231405-c4277021bca2/go.mod h1:jvrM3b0gPuIRiY1E/KmKfPk2XXDEKj7yFB+g9g0BItQ=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
--- a/patient/offer.go
+++ b/patient/offer.go
@@ -15,7 +15,7 @@
Access: router.PatientAuth,
Path: "patient/offer",
Validator: offer,
- After: plugins.Search | plugins.Services,
+ After: plugins.Search | plugins.Services, //|plugins.Offer
Redirect: "results.html",
}
router.AddPost(b)
@@ -23,7 +23,7 @@
func offer(r *http.Request, p *message.Printer) []string {
var errors []string
- data, err := forms.Parse(r)
+ data, err := forms.ParseMax(r, r.ContentLength)
if err != nil {
errors = append(errors, p.Sprint("Internal server error"))
return errors
@@ -45,7 +45,7 @@
if err != nil {
val.AddError("endDate", p.Sprint("Invalid end-date entered"))
}
- val.Require("")
+
if val.HasErrors() {
errors = append(errors, val.Messages()...)
}
--- a/patient/symptoms.go
+++ b/patient/symptoms.go
@@ -23,32 +23,44 @@
func symptoms(r *http.Request, p *message.Printer) []string {
var errors []string
+
data, err := forms.Parse(r)
if err != nil {
errors = append(errors, p.Sprint("Internal server error"))
return errors
}
+
val := data.Validator()
- // TODO(halfwit): Date must be in a reasonable range
+
+ // NOTE(halfwit) This is the current record oldest person
+ // Anything older than this is most definitely invalid
+ oldest := time.Date(1901, 1, 1, 0, 0, 0, 0, time.UTC)
+
+ // NOTE(halfwit) There's potential that symptoms started that day
+ // and the client is in a different time zone, use our tomorrow as a gate
+ youngest := time.Now().Add(time.Hour * 24)
+
val.Require("bday").Message(p.Sprint("Birth date required"))
- _, err = time.Parse("2006-01-02T15:04:05", r.Form.Get("bday"))
- if err != nil {
+ if d, e := time.Parse("2006-01-02T15:04:05", r.Form.Get("bday")); e != nil || oldest.After(d) || youngest.Before(d) {
val.AddError("bday", p.Sprint("Invalid birth date"))
}
+
val.Require("onset").Message(p.Sprint("Please enter the date and time your symptoms started"))
- _, err = time.Parse("2006-01-02T15:04:05", r.Form.Get("onset"))
- if err != nil {
+ if d, e := time.Parse("2006-01-02T15:04:05", r.Form.Get("onset")); e != nil || oldest.After(d) || youngest.Before(d) {
val.AddError("bday", p.Sprint("Invalid date"))
}
+
val.Require("gender").Message(p.Sprint("Please select a biological gender"))
if r.PostFormValue("gender") != "male" && r.PostFormValue("gender") != "female" {
val.AddError("gender", p.Sprint("Invalid selection for gender"))
}
+
val.GreaterOrEqual("duration", 0).Message(p.Sprint("Invalid value entered for how long symptoms have lasted"))
val.Require("reason").Message(p.Sprint("Please provide the reason for visit"))
val.Require("location").Message(p.Sprint("Please list the area the symptom(s) appear"))
val.Require("characteristic").Message(p.Sprint("Please provide a description of your symptoms"))
val.Require("aggreAlevi").Message(p.Sprint("Please note anything which improves/worsens your symptoms"))
+
for _, i := range []string{
"feversChills",
"wtGainLoss",
@@ -66,11 +78,14 @@
val.AddError(i, p.Sprintf("No selection for %s", i))
continue
}
+
if sel[0] == "Yes" || sel[0] == "yes" || sel[0] == "no" || sel[0] == "No" {
continue
}
+
val.AddError(i, p.Sprintf("Invalid selection for %s", i))
}
+
r.Form["pagetitle"] = []string{"Client symptoms"}
if val.HasErrors() {
errors = append(errors, val.Messages()...)