9898import type { DataTableSortMeta } from ' primevue/datatable' ;
9999import { FilterMatchMode } from ' @primevue/core/api' ;
100100import type { PkgInfo } from ' ~/shared/info' ;
101- import { cloneDeep , uniq } from ' es-toolkit/compat' ;
101+ import type { TestResult , Selection , Options } from ' ~/shared/testcases' ;
102+ import { defaultOptions , applySelection , testcasesToOptions , summariesToTestResult } from ' ~/shared/testcases' ;
102103
103104useHead ({ title: ' Test Cases' });
104105
@@ -126,74 +127,17 @@ watch(selectedTest, sel => dialogShow.value = sel ? true : false);
126127githubFetch <PkgInfo []>({
127128 path: " plugin/cargo/info/summaries.json"
128129}).then (val => {
129- testcases .value = summariesToTestResult (val );
130- testcasesFiltered .value = cloneDeep (testcases .value );
130+ const tc = summariesToTestResult (val );
131+ testcases .value = tc ;
132+ testcasesFiltered .value = applySelection (tc , selected );
131133});
132134
133- type TestResult = {
134- idx: number ,
135- user: string ,
136- repo: string ,
137- pkg: string ,
138- bin: string ,
139- kind: string ,
140- name: string ,
141- test_pass: string ,
142- test_duration_ms: number | null ,
143- test_error: string | null ,
144- miri_pass: string ,
145- miri_output: string | null ,
146- miri_timeout: string ,
147- };
148-
149- function summariesToTestResult(pkg_info : PkgInfo []): TestResult [] {
150- let result: TestResult [] = [];
151- let idx = 0 ;
152-
153- for (const info of pkg_info ) {
154- for (const [pkg, value] of Object .entries (info .pkgs )) {
155- for (const test of value .testcases ?.tests || []) {
156- for (const testcase of test .testcases ) {
157- result .push ({
158- idx: idx ++ ,
159- user: info .user ,
160- repo: info .repo ,
161- pkg ,
162- bin: test .binary_name ,
163- kind: test .kind ,
164- name: testcase .name ,
165- test_pass: testcase .status === " ok" ? " ✅" : (testcase .status === " failed" ? " ❌" : " " ),
166- test_duration_ms: testcase .duration_ms ,
167- test_error: testcase .error ,
168- miri_pass: testcase .miri_pass ? " ✅" : " ❌" ,
169- miri_output: testcase .miri_output ,
170- miri_timeout: testcase .miri_timeout ? " 💥" : " " ,
171- });
172- }
173- }
174- }
175- }
176-
177- return result ;
178- }
179-
180135function sortsChanged(meta ? : DataTableSortMeta [] | null ) {
181136 if (meta ) {
182137 selected .sorts = meta ;
183138 }
184139}
185-
186- const selected = reactive <{
187- user: string | null ,
188- repo: string | null ,
189- pkg: string | null ,
190- kind: string | null ,
191- test_pass: string | null ,
192- miri_pass: string | null ,
193- miri_timeout: string | null ,
194- text: any ,
195- sorts: DataTableSortMeta [],
196- }>({
140+ const selected = reactive <Selection >({
197141 user: null ,
198142 repo: null ,
199143 pkg: null ,
@@ -205,73 +149,71 @@ const selected = reactive<{
205149 sorts: [],
206150});
207151
208- type Options = {
209- user: string [],
210- repo: string [],
211- pkg: string [],
212- kind: string [],
213- test_pass: string [],
214- miri_pass: string [],
215- miri_timeout: string [],
216- };
217- function defaultOptions(): Options {
218- return {
219- user: [],
220- repo: [],
221- pkg: [],
222- kind: [],
223- test_pass: [],
224- miri_pass: [],
225- miri_timeout: [],
226- };
227- }
228152const options = reactive <{ val: Options }>({ val: defaultOptions () });
229153
230154// init options
231155watch (testcases , tc => options .val = testcasesToOptions (tc ));
232156
233157// update table when filter selection changes
234- watch (
235- selected ,
236- ({ user , repo , pkg , kind , test_pass , miri_pass , miri_timeout }) => {
237- // for simplicity, the data of testcases are supposed to remain unchanged
238- const chosen_testcases = testcases .value .filter (test => {
239- let chosen = true ;
240- if (user ) chosen && = test .user === user ;
241- if (repo ) chosen && = test .repo === repo ;
242- if (pkg ) chosen && = test .pkg === pkg ;
243- if (kind ) chosen && = test .kind === repo ;
244- if (test_pass ) chosen && = test .test_pass === test_pass ;
245- if (miri_pass ) chosen && = test .miri_pass === miri_pass ;
246- if (miri_timeout || miri_timeout === " " ) chosen && = test .miri_timeout === miri_timeout ;
247- return chosen ;
248- });
249- testcasesFiltered .value = chosen_testcases .map ((tc , idx ) => {
250- tc .idx = idx ;
251- return tc ;
158+ watch (selected , sel => testcasesFiltered .value = applySelection (testcases .value , sel ));
159+
160+ // ******************* route query *******************
161+ const route = useRoute ();
162+ function updateFilter(query : {
163+ user? : string ,
164+ repo? : string ,
165+ pkg? : string ,
166+ kind? : string ,
167+ test_pass? : string ,
168+ miri_pass? : string ,
169+ miri_timeout? : string ,
170+ text? : string ,
171+ sorts? : string ,
172+ }) {
173+ const { user, repo, pkg, kind, test_pass, miri_pass, miri_timeout, text, sorts } = query ;
174+
175+ // only support single value for each param
176+ // FIXME: empty string will not handled
177+ if (user ) selected .user = decodeURIComponent (user );
178+ if (repo ) selected .repo = decodeURIComponent (repo );
179+ if (pkg ) selected .pkg = decodeURIComponent (pkg );
180+ if (kind ) selected .kind = decodeURIComponent (kind );
181+ if (test_pass ) selected .test_pass = decodeURIComponent (test_pass );
182+ if (miri_pass ) selected .miri_pass = decodeURIComponent (miri_pass );
183+ if (miri_timeout ) selected .miri_timeout = decodeURIComponent (miri_timeout );
184+ if (text ) selected .text .global .value = decodeURIComponent (text );
185+
186+ if (sorts ) {
187+ const args = decodeURIComponent (sorts ).split (" ," );
188+ // @ts-ignore
189+ selected .sorts = args .map (arg => {
190+ let [field, order] = arg .split (" =" );
191+ return { field , order: parseInt (order ) };
252192 });
253- // options.val = testcasesToOptions(chosen_testcases);
254- });
255-
256- function testcasesToOptions(tc : TestResult []): Options {
257- let opts = defaultOptions ();
258- for (const test of tc ) {
259- opts .user .push (test .user );
260- opts .repo .push (test .repo );
261- opts .pkg .push (test .pkg );
262- opts .kind .push (test .kind );
263- opts .test_pass .push (test .test_pass );
264- opts .miri_pass .push (test .miri_pass );
265- opts .miri_timeout .push (test .miri_timeout );
266193 }
267-
268- opts .user = uniq (opts .user ).sort ();
269- opts .repo = uniq (opts .repo ).sort ();
270- opts .pkg = uniq (opts .pkg ).sort ();
271- opts .kind = uniq (opts .kind ).sort ();
272- opts .test_pass = uniq (opts .test_pass ).sort ();
273- opts .miri_pass = uniq (opts .miri_pass ).sort ();
274- opts .miri_timeout = uniq (opts .miri_timeout ).sort ();
275- return opts ;
276194}
195+ updateFilter (route .query );
196+
197+ const router = useRouter ();
198+ watch (selected , sel => {
199+ const { user, repo, pkg, kind, test_pass, miri_pass, miri_timeout, text, sorts } = sel ;
200+
201+ let query: any = {};
202+
203+ if (user ) query .user = encodeURIComponent (user );
204+ if (repo ) query .repo = encodeURIComponent (repo );
205+ if (pkg ) query .pkg = encodeURIComponent (pkg );
206+ if (kind ) query .kind = encodeURIComponent (kind );
207+ if (test_pass ) query .test_pass = encodeURIComponent (test_pass );
208+ if (miri_pass ) query .miri_pass = encodeURIComponent (miri_pass );
209+ if (miri_timeout ) query .miri_timeout = encodeURIComponent (miri_timeout );
210+ if (text .global .value ) query .text = encodeURIComponent (text .global .value );
211+
212+ if (sorts .length !== 0 ) {
213+ const args = sorts .map (({ field , order }) => order ? ` ${field }=${order } ` : null );
214+ query .sorts = encodeURIComponent (args .filter (x => x ).join (" ," ));
215+ }
216+
217+ router .push ({ path: route .path , query });
218+ });
277219 </script >
0 commit comments