github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/logfilters.test.ts (about) 1 import { Location } from "history" 2 import { 3 EMPTY_FILTER_TERM, 4 filterSetFromLocation, 5 parseTermInput, 6 TermState, 7 } from "./logfilters" 8 9 enum TestStrings { 10 Basic = "abc", 11 BuildCommand = 'Step 1 - 0.00s (Running command: [sh -c services="red" ./generate-start.sh] (in "/Users/lizz/Documents/Repos/pixeltilt/full"))', 12 BuildError404 = "Build Failed: ImageBuild: failed to compute cache key: failed to walk /var/lib/docker/tmp/buildkit-mount767282166/red: lstat /var/lib/docker/tmp/buildkit-mount767282166/red: no such file or directory", 13 BuildErrorInFile = "ERROR IN: [5/5] ADD storage/main ./", 14 BuildInfoLine = "[1/5] FROM docker.io/library/alpine@sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f", 15 SyntaxError = "→ render/start.go:9:33: syntax error: unexpected N, expecting comma or )", 16 } 17 18 describe("Log filters", () => { 19 describe("state generation", () => { 20 describe("for term filter", () => { 21 it("gets set with an empty state if no term is present", () => { 22 const emptyTermLocation = { search: "term=" } as Location 23 expect(filterSetFromLocation(emptyTermLocation).term).toEqual( 24 EMPTY_FILTER_TERM 25 ) 26 27 const noTermLocation = { search: "" } as Location 28 expect(filterSetFromLocation(noTermLocation).term).toEqual( 29 EMPTY_FILTER_TERM 30 ) 31 }) 32 33 it("gets set with a parsed state if a valid term is present", () => { 34 const textLocation = { search: "term=docker+build" } as Location 35 const textParsedTerm = filterSetFromLocation(textLocation).term 36 expect(textParsedTerm.state).toEqual(TermState.Parsed) 37 expect(textParsedTerm.input).toEqual("docker build") 38 expect(textParsedTerm.hasOwnProperty("regexp")).toBe(true) 39 expect(textParsedTerm.hasOwnProperty("error")).toBe(false) 40 41 const regexpLocation = { search: "term=%2Fdocker%2F" } as Location 42 const regexpParsedTerm = filterSetFromLocation(regexpLocation).term 43 expect(regexpParsedTerm.state).toEqual(TermState.Parsed) 44 expect(regexpParsedTerm.input).toEqual("/docker/") 45 expect(regexpParsedTerm.hasOwnProperty("regexp")).toBe(true) 46 expect(regexpParsedTerm.hasOwnProperty("error")).toBe(false) 47 }) 48 49 it("gets set with an error state if an invalid input is present", () => { 50 const location = { search: "term=%2Fdock(er%3F%2F" } as Location 51 const parsedTerm = filterSetFromLocation(location).term 52 expect(parsedTerm.state).toEqual(TermState.Error) 53 expect(parsedTerm.input).toEqual("/dock(er?/") 54 expect(parsedTerm.hasOwnProperty("regexp")).toBe(false) 55 expect(parsedTerm.hasOwnProperty("error")).toBe(true) 56 }) 57 }) 58 59 describe("term parsing", () => { 60 describe("for string literals", () => { 61 it("matches on the expected text", () => { 62 expect(parseTermInput("abc").test(TestStrings.Basic)).toBe(true) 63 expect(parseTermInput("SERVICE").test(TestStrings.BuildCommand)).toBe( 64 true 65 ) 66 expect( 67 parseTermInput("random phrase").test(TestStrings.BuildInfoLine) 68 ).toBe(false) 69 expect(parseTermInput("ab5d63").test(TestStrings.BuildInfoLine)).toBe( 70 true 71 ) 72 expect(parseTermInput("error").test(TestStrings.SyntaxError)).toBe( 73 true 74 ) 75 expect(parseTermInput("mount").test(TestStrings.BuildError404)).toBe( 76 true 77 ) 78 expect(parseTermInput("mount ").test(TestStrings.BuildError404)).toBe( 79 false 80 ) 81 }) 82 83 it("is not stateful", () => { 84 let parsed = parseTermInput("line 1") 85 expect(parsed.test("line 123")).toBe(true) 86 expect(parsed.test("line 124")).toBe(true) 87 expect(parsed.test("line 125")).toBe(true) 88 expect(parsed.test("line 126")).toBe(true) 89 }) 90 91 it("escapes any RegExp-specific characters", () => { 92 expect(parseTermInput("ab?c").test(TestStrings.Basic)).toBe(false) 93 expect(parseTermInput('"red"').test(TestStrings.BuildCommand)).toBe( 94 true 95 ) 96 expect( 97 parseTermInput("generate-start.sh").test(TestStrings.BuildCommand) 98 ).toBe(true) 99 expect(parseTermInput("w").test(TestStrings.BuildInfoLine)).toBe( 100 false 101 ) 102 expect( 103 parseTermInput("comma or )").test(TestStrings.SyntaxError) 104 ).toBe(true) 105 expect( 106 parseTermInput("ERROR.+").test(TestStrings.BuildErrorInFile) 107 ).toBe(false) 108 expect(parseTermInput("[1/5]").test(TestStrings.BuildInfoLine)).toBe( 109 true 110 ) 111 }) 112 }) 113 114 describe("for regular expressions", () => { 115 it("only parses strings surrounded by forward slashes as regexp", () => { 116 expect( 117 parseTermInput("/docker/").test(TestStrings.BuildInfoLine) 118 ).toBe(true) 119 expect( 120 parseTermInput("/docker").test(TestStrings.BuildInfoLine) 121 ).toBe(false) 122 }) 123 124 it("matches on the expected text", () => { 125 expect(parseTermInput("/ab?c/").test(TestStrings.Basic)).toBe(true) 126 expect( 127 parseTermInput("/error.+main/").test(TestStrings.BuildErrorInFile) 128 ).toBe(true) 129 expect(parseTermInput("/d+/").test(TestStrings.Basic)).toBe(false) 130 expect(parseTermInput("/d+/").test(TestStrings.BuildInfoLine)).toBe( 131 true 132 ) 133 expect( 134 parseTermInput("/failed:/").test(TestStrings.BuildError404) 135 ).toBe(true) 136 }) 137 138 it("throws an error when input text is invalid regex", () => { 139 expect(() => 140 parseTermInput("/(missing)? parenthesis)/") 141 ).toThrowError(/Invalid regular expression/) 142 }) 143 }) 144 }) 145 }) 146 })