11import { describe , expect , it } from "vitest" ;
2+ import { getRunFiltersFromSearchParams } from "~/components/runs/v3/RunFilters" ;
23import { appendRunFilters , navigateDestination , sameOriginPath } from "./navigate-target" ;
34
45const RUNS_PATH = "/orgs/acme/projects/api/env/prod/runs" ;
56
7+ const FAILING = [
8+ "COMPLETED_WITH_ERRORS" ,
9+ "SYSTEM_FAILURE" ,
10+ "CRASHED" ,
11+ "EXPIRED" ,
12+ "TIMED_OUT" ,
13+ "INTERRUPTED" ,
14+ ] ;
15+
16+ /** What the runs page makes of a URL this module produced. */
17+ function pageReads ( path : string ) {
18+ return getRunFiltersFromSearchParams (
19+ new URLSearchParams ( new URL ( path , "https://x.invalid" ) . search )
20+ ) ;
21+ }
22+
623describe ( "appendRunFilters" , ( ) => {
724 it ( "returns the path untouched with no filters" , ( ) => {
825 expect ( appendRunFilters ( RUNS_PATH ) ) . toBe ( RUNS_PATH ) ;
926 } ) ;
1027
1128 it ( "writes arrays as repeated params and keeps existing ones" , ( ) => {
1229 const result = appendRunFilters ( `${ RUNS_PATH } ?query=payments` , {
13- statuses : [ "FAILED " , "CRASHED" ] ,
30+ statuses : [ "COMPLETED_WITH_ERRORS " , "CRASHED" ] ,
1431 tasks : "send-email" ,
1532 period : "1d" ,
1633 } ) ;
1734
1835 expect ( result ) . toBe (
19- `${ RUNS_PATH } ?query=payments&statuses=FAILED &statuses=CRASHED&tasks=send-email&period=1d`
36+ `${ RUNS_PATH } ?query=payments&statuses=COMPLETED_WITH_ERRORS &statuses=CRASHED&tasks=send-email&period=1d`
2037 ) ;
2138 } ) ;
2239
@@ -30,6 +47,51 @@ describe("appendRunFilters", () => {
3047 expect ( appendRunFilters ( RUNS_PATH , { search : "" , rootOnly : false , tags : [ ] } ) ) . toBe ( RUNS_PATH ) ;
3148 expect ( appendRunFilters ( RUNS_PATH , { rootOnly : true } ) ) . toBe ( `${ RUNS_PATH } ?rootOnly=true` ) ;
3249 } ) ;
50+
51+ it ( "expands FAILED into the statuses the page calls failures" , ( ) => {
52+ const result = appendRunFilters ( RUNS_PATH , { statuses : [ "FAILED" ] , period : "1d" } ) ;
53+
54+ expect ( pageReads ( result ) ) . toEqual ( { statuses : FAILING , period : "1d" } ) ;
55+ } ) ;
56+
57+ it ( "takes the status the user said, however they cased it" , ( ) => {
58+ expect ( pageReads ( appendRunFilters ( RUNS_PATH , { statuses : "failed" } ) ) ) . toEqual ( {
59+ statuses : FAILING ,
60+ } ) ;
61+ } ) ;
62+
63+ it ( "passes a page-native status through untranslated" , ( ) => {
64+ const result = appendRunFilters ( RUNS_PATH , { statuses : [ "COMPLETED_SUCCESSFULLY" ] } ) ;
65+
66+ expect ( result ) . toBe ( `${ RUNS_PATH } ?statuses=COMPLETED_SUCCESSFULLY` ) ;
67+ expect ( pageReads ( result ) ) . toEqual ( { statuses : [ "COMPLETED_SUCCESSFULLY" ] } ) ;
68+ } ) ;
69+
70+ it ( "translates the other API status names the model borrows" , ( ) => {
71+ expect ( pageReads ( appendRunFilters ( RUNS_PATH , { statuses : [ "QUEUED" , "COMPLETED" ] } ) ) ) . toEqual ( {
72+ statuses : [ "PENDING" , "COMPLETED_SUCCESSFULLY" ] ,
73+ } ) ;
74+ } ) ;
75+
76+ it ( "drops a status the page cannot parse rather than losing every filter with it" , ( ) => {
77+ const result = appendRunFilters ( RUNS_PATH , { statuses : [ "NONSENSE" ] , period : "1d" } ) ;
78+
79+ expect ( result ) . toBe ( `${ RUNS_PATH } ?period=1d` ) ;
80+ expect ( pageReads ( result ) ) . toEqual ( { period : "1d" } ) ;
81+ } ) ;
82+
83+ // The page's parser has no `search`, and an unread param is only noise in the URL.
84+ it ( "leaves search out of the URL" , ( ) => {
85+ expect ( appendRunFilters ( RUNS_PATH , { search : "boom" , period : "1d" } ) ) . toBe (
86+ `${ RUNS_PATH } ?period=1d`
87+ ) ;
88+ } ) ;
89+
90+ // Control: the untranslated URL is what the live failure looked like. One status the
91+ // page cannot parse and it discards everything, the period included.
92+ it ( "pins why translation is needed: raw FAILED wipes the whole filter set" , ( ) => {
93+ expect ( pageReads ( `${ RUNS_PATH } ?statuses=FAILED&period=1d` ) ) . toEqual ( { } ) ;
94+ } ) ;
3395} ) ;
3496
3597describe ( "navigateDestination" , ( ) => {
@@ -38,7 +100,10 @@ describe("navigateDestination", () => {
38100 it ( "routes a dashboard path and applies the intent's filters" , ( ) => {
39101 expect (
40102 navigateDestination ( { path : RUNS_PATH , external : false } , { statuses : [ "FAILED" ] } )
41- ) . toEqual ( { kind : "route" , path : `${ RUNS_PATH } ?statuses=FAILED` } ) ;
103+ ) . toEqual ( {
104+ kind : "route" ,
105+ path : `${ RUNS_PATH } ?${ FAILING . map ( ( s ) => `statuses=${ s } ` ) . join ( "&" ) } ` ,
106+ } ) ;
42107 } ) ;
43108
44109 it ( "never routes a source file, it leaves the dashboard" , ( ) => {
0 commit comments