Make report coverage calendar expandable
This commit is contained in:
1 parent
4356160cc9
commit
6d1a98743f
11 files changed
+283
-57
No files matched your search
@@ -76,7 +76,7 @@ test('loading and failed reads never label days ungenerated and a retry can rest
|
||||
resolve(response(503,null,'DATABASE_QUERY_FAILED'));
|
||||
await reading;
|
||||
assert.equal(h.state.reportCalendarError,true);
|
||||
assert.match(block(h,`${month}-01`),/report_calendar.day_unknown/);
|
||||
assert.match(block(h,`${month}-01`),/report_calendar.unknown/);
|
||||
assert.doesNotMatch(h.element('#report-calendar-days').innerHTML,/is-ungenerated/);
|
||||
assert.equal(h.element('#report-calendar-retry').hidden,false);
|
||||
fail=false;
|
||||
@@ -272,7 +272,7 @@ test('calendar labels, status legends and read failures are translated in all th
|
||||
const context=vm.createContext({window:{},document:{readyState:'loading',addEventListener(){}}});
|
||||
vm.runInContext(fs.readFileSync(path.resolve(__dirname,'../../arr_web/static/i18n.js'),'utf8'),context);
|
||||
const catalog=context.window.ARRI18n.CATALOG;
|
||||
for(const key of ['title','widget_aria','generated','not_generated','unknown','loading_day',
|
||||
for(const key of ['title','widget_aria','open','loading_summary','failed_summary','generated','not_generated','unknown','loading_day',
|
||||
'day_generated','day_not_generated','day_unknown','day_loading_day','loading','failed','coverage','help','locked','day_group','legend','retry']) {
|
||||
const entry=catalog[`report_calendar.${key}`];
|
||||
assert.equal(entry?.length,3,key);
|
||||
@@ -324,3 +324,130 @@ test('same-date selections across an environment A to B to A transition reject t
|
||||
assert.equal(h.state.dailyOverviewDate,date);
|
||||
assert.equal(h.state.jobsMonth,month);
|
||||
});
|
||||
|
||||
test('the compact calendar starts closed and its popup and ARR date picker are mutually exclusive',async()=>{
|
||||
const h=setup(()=>page([row(16)]));
|
||||
await h.loadReportCalendar();
|
||||
assert.equal(h.element('#report-calendar-popup').hidden,true);
|
||||
assert.equal(h.element('#report-calendar-toggle').getAttribute('aria-expanded'),'false');
|
||||
assert.equal(h.element('#report-calendar-summary').textContent,'report_calendar.coverage');
|
||||
const reads=h.calls.length;
|
||||
h.openARRCalendar();
|
||||
assert.equal(h.arrCalendar.open,true);
|
||||
h.openReportCalendar();
|
||||
assert.equal(h.arrCalendar.open,false);
|
||||
assert.equal(h.state.reportCalendarOpen,true);
|
||||
assert.equal(h.element('#report-calendar-popup').hidden,false);
|
||||
assert.equal(h.element('#report-calendar-toggle').getAttribute('aria-expanded'),'true');
|
||||
assert.match(block(h,`${month}-16`),/report-calendar-day-check/,'a generated day has a non-color check mark');
|
||||
assert.doesNotMatch(block(h,`${month}-17`),/report-calendar-day-check|report-calendar-day-state/);
|
||||
h.openARRCalendar();
|
||||
assert.equal(h.state.reportCalendarOpen,false);
|
||||
assert.equal(h.element('#report-calendar-popup').hidden,true);
|
||||
assert.equal(h.arrCalendar.open,true);
|
||||
assert.equal(h.calls.length,reads,'opening either calendar is a view action');
|
||||
});
|
||||
|
||||
test('Escape and close return focus to the trigger while outside click or keyboard focus preserve the destination',()=>{
|
||||
const h=setup(()=>{throw new Error('Closing must not request data');});
|
||||
h.bindReportCalendar();
|
||||
h.openReportCalendar();
|
||||
let prevented=false;
|
||||
h.emitDocumentEvent({type:'keydown',key:'Escape',preventDefault(){prevented=true;}});
|
||||
assert.equal(prevented,true);
|
||||
assert.equal(h.state.reportCalendarOpen,false);
|
||||
assert.equal(h.document.activeElement,h.element('#report-calendar-toggle'));
|
||||
h.openReportCalendar();
|
||||
h.element('#report-calendar-close').dispatchEvent({type:'click'});
|
||||
assert.equal(h.state.reportCalendarOpen,false);
|
||||
assert.equal(h.document.activeElement,h.element('#report-calendar-toggle'));
|
||||
for(const type of ['click','focusin']) {
|
||||
h.openReportCalendar();
|
||||
const destination=h.element('#xml-file');
|
||||
destination.focus();
|
||||
h.emitDocumentEvent({type,target:destination});
|
||||
assert.equal(h.state.reportCalendarOpen,false);
|
||||
assert.equal(h.document.activeElement,destination,'dismissal cannot steal focus from the next operation');
|
||||
}
|
||||
});
|
||||
|
||||
test('successful read-only selection closes the popup but busy or unsaved prices keep it open without discarding input',async()=>{
|
||||
const date=`${month}-17`;
|
||||
const h=setup(url=>url===`/api/daily-reports/${date}`?response(200,{business_date:date,current_job:null,latest_job:null}):page());
|
||||
await h.loadReportCalendar();
|
||||
h.openReportCalendar();
|
||||
h.state.uploadInFlight=true;
|
||||
assert.equal(await h.selectReportCalendarDate(date),false);
|
||||
assert.equal(h.state.reportCalendarOpen,true);
|
||||
h.state.uploadInFlight=false;
|
||||
h.state.dailyPriceReview={case_status:'open',items:[{item_id:1,real_price:null}]};
|
||||
const input={value:'0',closest:()=>({dataset:{dailyPriceReviewItemId:'1'}})};
|
||||
h.element('#daily-price-review-body').querySelectorAll=()=>[input];
|
||||
assert.equal(await h.selectReportCalendarDate(date),false);
|
||||
assert.equal(h.state.reportCalendarOpen,true);
|
||||
assert.equal(input.value,'0');
|
||||
assert.equal(h.element('#arr-download-date').value,`${month}-16`);
|
||||
h.state.dailyPriceReview=null;
|
||||
assert.equal(await h.selectReportCalendarDate(date),true);
|
||||
assert.equal(h.state.reportCalendarOpen,false);
|
||||
assert.equal(h.element('#report-calendar-popup').hidden,true);
|
||||
assert.equal(h.document.activeElement,h.element('#report-calendar-toggle'));
|
||||
assert.equal(h.calls.every(call=>call.method==='GET'),true);
|
||||
assert.equal(h.calls.some(call=>call.url.includes('/arr-downloads')),false);
|
||||
});
|
||||
|
||||
test('a hidden popup never captures focus during a late month refresh or keyboard-render request',async()=>{
|
||||
let resolveRead;
|
||||
const h=setup(()=>new Promise(resolve=>{resolveRead=resolve;}));
|
||||
h.openReportCalendar();
|
||||
const pending=h.loadReportCalendar();
|
||||
const hiddenDay=h.element(`[data-report-calendar-day="${h.state.reportCalendarFocusDate}"]`);
|
||||
hiddenDay.closest=()=>hiddenDay;
|
||||
h.closeReportCalendar();
|
||||
let focusAttempts=0;
|
||||
hiddenDay.focus=()=>{focusAttempts+=1;};
|
||||
h.document.activeElement=hiddenDay;
|
||||
resolveRead(page());
|
||||
await pending;
|
||||
h.renderReportCalendar(true);
|
||||
assert.equal(focusAttempts,0);
|
||||
assert.equal(h.element('#report-calendar-popup').hidden,true);
|
||||
});
|
||||
|
||||
test('a late day selection cannot close a popup opened again after the original popup was dismissed',async()=>{
|
||||
let resolveSelection;
|
||||
const date=`${month}-17`;
|
||||
const h=setup(url=>url===`/api/daily-reports/${date}`?new Promise(resolve=>{resolveSelection=resolve;}):page());
|
||||
await h.loadReportCalendar();
|
||||
h.openReportCalendar();
|
||||
const selecting=h.selectReportCalendarDate(date);
|
||||
h.closeReportCalendar();
|
||||
h.openReportCalendar();
|
||||
resolveSelection(response(200,{business_date:date,current_job:null,latest_job:null}));
|
||||
assert.equal(await selecting,true);
|
||||
assert.equal(h.state.reportCalendarOpen,true);
|
||||
assert.equal(h.element('#report-calendar-popup').hidden,false);
|
||||
});
|
||||
|
||||
test('a delegated day click stays internal after synchronous rendering removes its target and restores trigger focus on success',async()=>{
|
||||
let resolveSelection;
|
||||
const date=`${month}-17`;
|
||||
const h=setup(url=>url===`/api/daily-reports/${date}`?new Promise(resolve=>{resolveSelection=resolve;}):page());
|
||||
await h.loadReportCalendar();
|
||||
h.bindReportCalendar();
|
||||
h.openReportCalendar();
|
||||
const originalButton={dataset:{reportCalendarDay:date},closest(){return this;}};
|
||||
const control=h.element('#report-calendar');
|
||||
const event={type:'click',target:originalButton,composedPath:()=>[
|
||||
originalButton,h.element('#report-calendar-days'),h.element('#report-calendar-popup'),control]};
|
||||
h.element('#report-calendar-days').dispatchEvent(event);
|
||||
assert.equal(h.state.dailyOverviewDate,date,'the delegated handler has already synchronously rerendered the days');
|
||||
assert.equal(control.contains(originalButton),false,'the original click target is no longer a current DOM descendant');
|
||||
h.emitDocumentEvent(event);
|
||||
assert.equal(h.state.reportCalendarOpen,true,'document must honor the event origin instead of the removed target');
|
||||
resolveSelection(response(200,{business_date:date,current_job:null,latest_job:null}));
|
||||
await new Promise(resolve=>setImmediate(resolve));
|
||||
assert.equal(h.state.reportCalendarOpen,false);
|
||||
assert.equal(h.document.activeElement,h.element('#report-calendar-toggle'));
|
||||
assert.equal(h.calls.every(call=>call.method==='GET'),true);
|
||||
});
|
||||
Reference in new issue
Block a user