diff --git a/main.go b/main.go index 4c686026..d8af25ad 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func configure(app *aero.Application) *aero.Application { app.OnShutdown(arn.Node.Close) // Check that this is the server - if !arn.Node.IsServer() { + if !arn.Node.IsServer() && !arn.IsTest() { panic("Another program is currently running as the database server") } diff --git a/main_test.go b/main_test.go index 57037505..45260e9d 100644 --- a/main_test.go +++ b/main_test.go @@ -9,17 +9,22 @@ import ( "github.com/aerogo/aero" ) -func TestRoutes(t *testing.T) { +// TestRouteStatusCodes tests the status code of every route registered in routeTests. +func TestRouteStatusCodes(t *testing.T) { app := configure(aero.New()) + // Iterate through every route for _, examples := range routeTests { + // Iterate through every example specified for that route for _, example := range examples { + // Create a new HTTP request request, err := http.NewRequest("GET", example, nil) if err != nil { t.Fatal(err) } + // Record the response without actually starting the server responseRecorder := httptest.NewRecorder() app.Handler().ServeHTTP(responseRecorder, request) diff --git a/makefile b/makefile index 111cd749..4a3923dc 100644 --- a/makefile +++ b/makefile @@ -3,7 +3,7 @@ GOCMD=@go GOBUILD=$(GOCMD) build GOINSTALL=$(GOCMD) install -GOTEST=@./go-test-color.sh +GOTEST=@./utils/test/go-test-color.sh BUILDJOBS=@./jobs/build.sh BUILDPATCHES=@./patches/build.sh BUILDBOTS=@./bots/build.sh @@ -39,7 +39,7 @@ js: install: $(GOINSTALL) test: - $(GOTEST) github.com/animenotifier/... -v -cover + $(GOTEST) github.com/animenotifier/notify.moe -v -cover bench: $(GOTEST) -bench . tools: diff --git a/mixins/AnimeEditorList.pixy b/mixins/AnimeEditorList.pixy index 909bbb24..5ce6134f 100644 --- a/mixins/AnimeEditorList.pixy +++ b/mixins/AnimeEditorList.pixy @@ -9,6 +9,7 @@ component AnimeEditorList(animes []*arn.Anime, pageURI string, generateSearchLin thead tr.mountable th(title="Popularity") Pop. + th Image th Title th Type th Year @@ -19,6 +20,8 @@ component AnimeEditorList(animes []*arn.Anime, pageURI string, generateSearchLin each anime in animes tr.mountable td= anime.Popularity.Total() + td + img.anime-list-item-image.lazy(data-src=anime.ImageLink("small"), data-webp="true", data-color=anime.AverageColor(), alt=anime.Title.Canonical) td a(href=anime.Link(), target="_blank", rel="noopener")= anime.Title.Canonical td= anime.Type diff --git a/patches/import-mal-companies/import-mal-companies.go b/patches/import-mal-companies/import-mal-companies.go index f8b143e7..e6ea498d 100644 --- a/patches/import-mal-companies/import-mal-companies.go +++ b/patches/import-mal-companies/import-mal-companies.go @@ -79,8 +79,6 @@ func importByName(anime *arn.Anime, companyType string, producer *mal.Producer) &arn.Mapping{ Service: "myanimelist/producer", ServiceID: producer.ID, - Created: arn.DateTimeUTC(), - CreatedBy: "", }, }, Links: []*arn.Link{}, diff --git a/scripts/Experimental/Diff-onMutationsQueued.ts b/scripts/Experimental/Diff-onMutationsQueued.ts deleted file mode 100644 index 9b45c59c..00000000 --- a/scripts/Experimental/Diff-onMutationsQueued.ts +++ /dev/null @@ -1,39 +0,0 @@ -// let diffStart: number -// let diffMountableCount: number - -// Diff.onStart = () => { -// diffMountableCount = 0 -// } - -// Diff.onMutationsQueued = elem => { -// Diff.mutations.queue(() => { -// // Mountable -// if(elem.classList.contains("mountable")) { -// diffMountableCount++ - -// let now = Date.now() - -// if(diffMountableCount === 1) { -// diffStart = now -// } - -// const mountTime = diffMountableCount * 20 + diffStart - -// if(mountTime > now && mountTime < now + 800) { -// let mount = () => { -// if(Date.now() >= mountTime) { -// elem.classList.add("mounted") -// } else { -// Diff.mutations.queue(mount) -// } -// } - -// Diff.mutations.queue(mount) -// } else { -// elem.classList.add("mounted") -// } -// } else if(elem.classList.contains("lazy")) { -// this.lazyLoadElement(elem) -// } -// }) -// } \ No newline at end of file diff --git a/scripts/Experimental/Diff-with-callbacks.ts b/scripts/Experimental/Diff-with-callbacks.ts deleted file mode 100644 index e3b70011..00000000 --- a/scripts/Experimental/Diff-with-callbacks.ts +++ /dev/null @@ -1,178 +0,0 @@ -// import { MutationQueue, CustomMutationQueue } from "./MutationQueue" - -// export class Diff { -// static persistentClasses = new Set() -// static persistentAttributes = new Set() - -// // Reuse container for diffs to avoid memory allocation -// static container: HTMLElement -// static rootContainer: HTMLElement -// static mutations: CustomMutationQueue = new CustomMutationQueue() - -// // Callbacks -// static onStart: () => void -// static onMutationsQueued: (elem: HTMLElement) => void - -// // innerHTML will diff the element with the given HTML string and apply DOM mutations. -// static innerHTML(aRoot: HTMLElement, html: string): Promise { -// return new Promise((resolve, reject) => { -// if(!Diff.container) { -// Diff.container = document.createElement("main") -// } - -// Diff.container.innerHTML = html - -// if(Diff.onStart) { -// Diff.onStart() -// } - -// Diff.childNodes(aRoot, Diff.container) -// this.mutations.wait(resolve) -// }) -// } - -// // root will diff the document root element with the given HTML string and apply DOM mutations. -// static root(aRoot: HTMLElement, html: string) { -// return new Promise((resolve, reject) => { -// if(!Diff.rootContainer) { -// Diff.rootContainer = document.createElement("html") -// } - -// Diff.rootContainer.innerHTML = html.replace("", "") - -// if(Diff.onStart) { -// Diff.onStart() -// } - -// Diff.childNodes(aRoot.getElementsByTagName("body")[0], Diff.rootContainer.getElementsByTagName("body")[0]) -// this.mutations.wait(resolve) -// }) -// } - -// // childNodes diffs the child nodes of 2 given elements and applies DOM mutations. -// static childNodes(aRoot: Node, bRoot: Node) { -// let aChild = [...aRoot.childNodes] -// let bChild = [...bRoot.childNodes] -// let numNodes = Math.max(aChild.length, bChild.length) - -// for(let i = 0; i < numNodes; i++) { -// let a = aChild[i] - -// // Remove nodes at the end of a that do not exist in b -// if(i >= bChild.length) { -// this.mutations.queue(() => aRoot.removeChild(a)) -// continue -// } - -// let b = bChild[i] - -// // If a doesn't have that many nodes, simply append at the end of a -// if(i >= aChild.length) { -// this.mutations.queue(() => aRoot.appendChild(b)) - -// if(Diff.onMutationsQueued && b.nodeType === Node.ELEMENT_NODE) { -// Diff.onMutationsQueued(b as HTMLElement) -// } - -// continue -// } - -// // If it's a completely different HTML tag or node type, replace it -// if(a.nodeName !== b.nodeName || a.nodeType !== b.nodeType) { -// this.mutations.queue(() => aRoot.replaceChild(b, a)) - -// if(Diff.onMutationsQueued && b.nodeType === Node.ELEMENT_NODE) { -// Diff.onMutationsQueued(b as HTMLElement) -// } - -// continue -// } - -// // Text node: -// // We don't need to check for b to be a text node as well because -// // we eliminated different node types in the previous condition. -// if(a.nodeType === Node.TEXT_NODE) { -// this.mutations.queue(() => a.textContent = b.textContent) -// continue -// } - -// // HTML element: -// if(a.nodeType === Node.ELEMENT_NODE) { -// let elemA = a as HTMLElement -// let elemB = b as HTMLElement - -// let removeAttributes: Attr[] = [] - -// for(let x = 0; x < elemA.attributes.length; x++) { -// let attrib = elemA.attributes[x] - -// if(attrib.specified) { -// if(!elemB.hasAttribute(attrib.name) && !Diff.persistentAttributes.has(attrib.name)) { -// removeAttributes.push(attrib) -// } -// } -// } - -// this.mutations.queue(() => { -// for(let attr of removeAttributes) { -// elemA.removeAttributeNode(attr) -// } -// }) - -// for(let x = 0; x < elemB.attributes.length; x++) { -// let attrib = elemB.attributes[x] - -// if(!attrib.specified) { -// continue -// } - -// // If the attribute value is exactly the same, skip this attribute. -// if(elemA.getAttribute(attrib.name) === attrib.value) { -// continue -// } - -// if(attrib.name === "class") { -// let classesA = elemA.classList -// let classesB = elemB.classList -// let removeClasses: string[] = [] - -// for(let className of classesA) { -// if(!classesB.contains(className) && !Diff.persistentClasses.has(className)) { -// removeClasses.push(className) -// } -// } - -// this.mutations.queue(() => { -// for(let className of removeClasses) { -// classesA.remove(className) -// } - -// for(let className of classesB) { -// if(!classesA.contains(className)) { -// classesA.add(className) -// } -// } -// }) - -// continue -// } - -// this.mutations.queue(() => elemA.setAttribute(attrib.name, attrib.value)) -// } - -// // Special case: Apply state of input elements -// if(elemA !== document.activeElement && elemA instanceof HTMLInputElement && elemB instanceof HTMLInputElement) { -// this.mutations.queue(() => { -// (elemA as HTMLInputElement).value = (elemB as HTMLInputElement).value -// }) -// } -// } - -// Diff.childNodes(a, b) - -// if(Diff.onMutationsQueued && a.nodeType === Node.ELEMENT_NODE) { -// Diff.onMutationsQueued(a as HTMLElement) -// } -// } -// } -// } \ No newline at end of file diff --git a/utils/test/go-test-color.sh b/utils/test/go-test-color.sh new file mode 100755 index 00000000..51b8cf02 --- /dev/null +++ b/utils/test/go-test-color.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# Colorizing Go test output: +# This is meant to be used in place of `go test`. Provided this script is in +# your PATH, calling `color-go-test` will call through to `go test` and then +# colorize and reformat the output. + +RED=$(tput setaf 1) +GREEN=$(tput setaf 2) +YELLOW=$(tput setaf 3) +COLOR_RESET=$(tput sgr0) +BOLD=$(tput bold) + +previous_line_fail=false +verbose_output=false +verbose_flag_prefix="-v " +pass_count=0 +fail_count=0 +errors=() + +echo_last_line() { + local time_string=$1 + local color=$GREEN + if [ $verbose_output = false ]; then + echo -e "\n" + if [ ${#errors[@]} -gt 0 ]; then + for error in "${errors[@]}"; do + echo -e "$error" + done + fi + fi + if [ $fail_count -gt 0 ]; then + color=$RED + fi + local num_tests=$((pass_count + fail_count)) + echo -e "\n${color}${BOLD}$num_tests tests, $fail_count failure, run time ($time_string)${COLOR_RESET}" +} + +colorize_output() { + while read line; do + if echo $line | grep --quiet '^FAIL$'; then + continue + + elif echo $line | grep --quiet '^PASS$'; then + continue + + elif echo $line | grep --quiet '^=== RUN'; then + continue + + elif echo $line | grep --quiet '^exit status 1$'; then + continue + + elif echo $line | grep --quiet 'FAIL'; then + if echo $line | grep --quiet "\-\-\- FAIL:"; then + fail_count=$((fail_count + 1)) + error_message="${RED}$(echo $line | sed 's/--- FAIL:/✗/')${COLOR_RESET}" + + if [ $verbose_output = true ]; then + echo $error_message + else + errors+=("$error_message") + printf "${RED}.${COLOR_RESET}" + fi + previous_line_fail=true + else + local test_run_time=$(echo $line | grep -o '[0-9]*\.[0-9]*s$') + echo_last_line $test_run_time + previous_line_fail=false + fi + + elif [ $previous_line_fail = true ]; then + error_message=" ${YELLOW}➝ $line${COLOR_RESET}" + if [ $verbose_output = true ]; then + echo -e "$error_message" + else + errors+=("$error_message") + fi + previous_line_fail=false + + elif echo $line | grep --quiet 'PASS'; then + if echo $line | grep --quiet "\-\-\- PASS:"; then + if [ $verbose_output = true ]; then + echo "${GREEN}$(echo $line | sed 's/--- PASS:/✔/')${COLOR_RESET}" + else + printf "${GREEN}.${COLOR_RESET}" + fi + pass_count=$((pass_count + 1)) + else + local test_run_time=$(echo $line | grep -o '[0-9]*\.[0-9]*s$') + echo_last_line $test_run_time + fi + + previous_line_fail=false + + elif echo $line | grep --quiet '^ok '; then + local test_run_time=$(echo $line | grep -o '[0-9]*\.[0-9]*s$') + echo_last_line $test_run_time + previous_line_fail=false + + else + echo $line + previous_line_fail=false + fi + done +} + +for flag in $@; do + if [ "$flag" = "-v" ]; then + verbose_output=true + verbose_flag_prefix="" + fi +done + +go test ${verbose_flag_prefix}$@ | colorize_output