From c672ec1666a2c8f0773131bb61f67fb0de6f0fe1 Mon Sep 17 00:00:00 2001 From: robinknaapen Date: Sat, 26 Aug 2017 23:44:47 +0200 Subject: [PATCH] Initial commit --- serializer.js | 110 +++++++++++++++++++++++++++++ tests/main.go | 133 ++++++++++++++++++++++++++++++++++++ tests/templates/test.gohtml | 52 ++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 serializer.js create mode 100644 tests/main.go create mode 100644 tests/templates/test.gohtml diff --git a/serializer.js b/serializer.js new file mode 100644 index 0000000..9046429 --- /dev/null +++ b/serializer.js @@ -0,0 +1,110 @@ +class SerializerField { + /** + * constructor + * + * @param {HTMLElement} f Input field (input|select|textarea) + * @returns {SerializerField} + */ + constructor(f){ + this.field = f; + } + + /** + * serialize + * + * @returns {(String|Number)} + */ + serialize(){ + let type = this.field.getAttribute("type"); + if(type == "number" || type == "range"){ + return Number(this.field.value); + } else if(type == "date" || type == "datetime-local" || type == "month" || type == "week") { + return new Date(this.field.value); + } else { + return this.field.value; + } + } +} + +class Serializer { + /** + * constructor + * + * @param {HTMLElement} element + * @returns {Serializer} + */ + constructor(element){ + let fields = element.querySelectorAll(`:scope > input:not([type="submit"]), :scope > select, :scope > textarea, :scope > group`); + + this._fields = new Map(); + + for(let f of fields){ + this.addField(f); + } + } + + /** + * addField + * + * @param {HTMLElement} f + */ + addField(f){ + let fieldName = f.getAttribute("name"); + let isArray = fieldName.match(/^\[(\d*)\]/) + + let field; + if(f.tagName == "GROUP"){ + field = new Serializer(f) + } else { + field = new SerializerField(f); + } + + if(isArray){ + fieldName = fieldName.replace(/^\[(\d*)\]/, ''); + if(!this._fields.has(fieldName)){ + this._fields.set(fieldName, []) + } + if(isArray[1] != ""){ + this._fields.get(fieldName)[isArray[1]] = field + } else { + this._fields.get(fieldName).push(field) + } + } else { + this._fields.set(fieldName, field) + } + } + + /** + * serialize + * + * @returns {Object} + */ + serialize(){ + let json = {}; + for(let [k, f] of this._fields){ + if(Array.isArray(f)){ + if(k != ""){ + json[k] = []; + } else { + json = []; + } + for(let key in f){ + if(f[key]){ + if(k == ""){ + json[key] = f[key].serialize() + continue; + } + json[k][key] = f[key].serialize() + } + } + } else { + if(k == ""){ + json = f.serialize() + continue; + } + json[k] = f.serialize() + } + } + return json; + } +} diff --git a/tests/main.go b/tests/main.go new file mode 100644 index 0000000..fbd70e2 --- /dev/null +++ b/tests/main.go @@ -0,0 +1,133 @@ +package main + +import ( + "encoding/json" + "fmt" + "html/template" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "os/exec" + "reflect" + "text/tabwriter" + "time" + + "github.com/fatih/color" + "github.com/julienschmidt/httprouter" +) + +var templates *template.Template +var tw *tabwriter.Writer +var testData = []*Person{ + &Person{ + Name: "Foo", + Surname: "Bar", + Age: 57, + BirthDate: time.Date(1960, 1, 1, 0, 0, 0, 0, time.UTC), + }, + nil, + &Person{ + Name: "Crow", + Surname: "CrowCrow", + Age: 22, + BirthDate: time.Date(1995, 1, 5, 0, 0, 0, 0, time.UTC), + Languages: []Language{ + Language{ + Language: "Dutch", + SkillLevel: 9.99, + }, + Language{ + Language: "English", + SkillLevel: 8.4, + }, + Language{ + Language: "Marokaans", + SkillLevel: -9000.9, + }, + }, + }, +} + +func main() { + router := httprouter.New() + + router.GET("/", getTest) + router.POST("/", postTest) + + router.ServeFiles("/static/*filepath", http.Dir("../")) + + var err error + templates, err = template.ParseGlob(`templates/*.gohtml`) + if err != nil { + fmt.Println(err) + return + } + + tw = tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) + + server := httptest.NewServer(router) + + exec.Command("chromium", "--headless", "--disable-gpu", server.URL).Run() + // TODO: Fix closing FF + exec.Command("firefox", "-headless", server.URL).Run() +} + +// Person ... +type Person struct { + Name string `json:"name"` + Surname string `json:"surname"` + Age int `json:"age"` + BirthDate time.Time `json:"birth_date"` + Languages []Language `json:"languages"` +} + +// Languages ... +type Language struct { + Language string `json:"language"` + SkillLevel float64 `json:"skill_level"` +} + +func getTest(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + templates.ExecuteTemplate(w, `test.gohtml`, testData) +} + +func postTest(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + body, _ := ioutil.ReadAll(r.Body) + + var p []*Person + + err := json.Unmarshal(body, &p) + if err != nil { + fmt.Println(err) + fmt.Println("Person could not be decoded") + } + + for k := range p { + if p[k] == nil && testData[k] == nil { + continue + } + isEq(*p[k], *testData[k]) + } + tw.Flush() +} + +func isEq(p1, p2 Person) { + assert(p1.Name, p2.Name, "Name") + assert(p1.Surname, p2.Surname, "Surname") + assert(p1.Age, p2.Age, "Age") + assert(p1.BirthDate, p2.BirthDate, "BirthDate") + for k := range p1.Languages { + assert(p1.Languages[k].Language, p2.Languages[k].Language, "Languages.Language") + assert(p1.Languages[k].SkillLevel, p2.Languages[k].SkillLevel, "Languages.SkillLevel") + } +} + +func assert(v, v2 interface{}, ident string) { + if !reflect.DeepEqual(v, v2) { + fmt.Fprint(tw, color.RedString("FAIL\t")) + } else { + fmt.Fprint(tw, color.GreenString("PASS\t")) + } + fmt.Fprintf(tw, "%s\t%s\n", color.BlueString(ident), color.YellowString(fmt.Sprintf("'%v'\t'%v'", v, v2))) +} diff --git a/tests/templates/test.gohtml b/tests/templates/test.gohtml new file mode 100644 index 0000000..2f9944b --- /dev/null +++ b/tests/templates/test.gohtml @@ -0,0 +1,52 @@ + + + + + test + + + + +
+ {{ range $k, $p := . }} + {{ if $p }} + + + + + + {{ range $p.Languages }} + + + + + {{ end }} + + {{ end }} + {{ end }} +
+ + +