fix bugs
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { createRequire } from 'node:module';
|
||||
const require = createRequire(import.meta.url);
|
||||
const dayjs = require('../uni_modules/uview-ui/libs/util/dayjs.js');
|
||||
const utilitySource = await readFile(new URL('../common/roomCalendarUi.js',import.meta.url),'utf8');
|
||||
const ui = await import('data:text/javascript;base64,'+Buffer.from(utilitySource).toString('base64'));
|
||||
const pageSource = await readFile(new URL('../pages/roomCalendar/roomCalendar.vue',import.meta.url),'utf8');
|
||||
const appSource = await readFile(new URL('../App.vue',import.meta.url),'utf8');
|
||||
const tabMethod = appSource.slice(appSource.indexOf('showTabbarByPermission(userData){'),
|
||||
appSource.indexOf('// 返回',appSource.indexOf('showTabbarByPermission(userData){'))).trim().replace(/,$/,'');
|
||||
const applyTabPermissions = new Function('uni',`return ({${tabMethod}}).showTabbarByPermission;`);
|
||||
const script = pageSource.match(/<script>([\s\S]*?)<\/script>/)[1]
|
||||
.replace(/import[\s\S]*?from\s+['"][^'"]+['"];?/g,'').replace('export default','return');
|
||||
function setup({permission=true,metadata,availability}={}) {
|
||||
const calls = [];
|
||||
const toasts = [];
|
||||
const user = {canViewCalendar:permission};
|
||||
globalThis.uni = {
|
||||
getLocale:()=> 'en', getStorageSync:()=>user,
|
||||
showLoading(){},hideLoading(){},$u:{toast:m=>toasts.push(m)}
|
||||
};
|
||||
const page = new Function('dayjs','buildCalendarDateRange','getTodayWeekId',
|
||||
'mapRoomCalendarQualificationRecords','getPropertiesRoomTypes','requestRoomCalendar',
|
||||
'requestCalendarSetting',script)(dayjs,ui.buildCalendarDateRange,ui.getTodayWeekId,
|
||||
ui.mapRoomCalendarQualificationRecords,
|
||||
async()=>{calls.push('metadata');return metadata ?? {success:true,propertyList:[
|
||||
{code:'Macau',roomTypes:[{code:'SUITE',label:'SUITE'}],defaultRoomTypes:['SUITE']}
|
||||
]};},
|
||||
async(params,config)=>{calls.push(params);return availability ? availability(params,config) : {success:true,data:[]};},
|
||||
async()=>{calls.push('settings');return {success:true,data:[]};});
|
||||
const vm = {$t:k=>k,$i18n:{},$nextTick:fn=>fn(),showTabbarByPermission(){}};
|
||||
Object.assign(vm,page.data.call(vm));
|
||||
vm.userData = user;
|
||||
for(const [key,fn] of Object.entries(page.methods)) vm[key]=fn.bind(vm);
|
||||
for(const [key,fn] of Object.entries(page.computed)) Object.defineProperty(vm,key,{get:fn.bind(vm)});
|
||||
return {vm,page,calls,toasts};
|
||||
}
|
||||
test('direct navigation and refresh without permission issue no queries',async()=>{
|
||||
const {vm,page,calls}=setup({permission:false});
|
||||
page.onShow.call(vm);
|
||||
vm.refreshCalendar();
|
||||
await vm.loadPropertiesRoomTypes();
|
||||
assert.equal(vm.calendarNoPermission,true);
|
||||
assert.equal(vm.calendarReady,false);
|
||||
assert.deepEqual(calls,[]);
|
||||
});
|
||||
|
||||
test('real tab permission method hides Calendar after an allowed user switches to a denied user',()=>{
|
||||
const visible = new Map();
|
||||
const apply = applyTabPermissions({setTabBarItem:({index,visible:value})=>visible.set(index,value)});
|
||||
apply({canViewCalendar:true});
|
||||
assert.equal(visible.get(3),true);
|
||||
for (const user of [{canViewCalendar:false},{},{canViewCalendar:'true'},null,undefined]) {
|
||||
apply({canViewCalendar:true});
|
||||
apply(user);
|
||||
assert.equal(visible.get(3),false);
|
||||
}
|
||||
});
|
||||
|
||||
test('page onShow applies real tab visibility and blocks denied users before any query',()=>{
|
||||
const {vm,page,calls}=setup({permission:false});
|
||||
const visible = new Map();
|
||||
vm.showTabbarByPermission = applyTabPermissions({setTabBarItem:({index,visible:value})=>visible.set(index,value)});
|
||||
page.onShow.call(vm);
|
||||
assert.equal(visible.get(3),false);
|
||||
assert.equal(vm.calendarNoPermission,true);
|
||||
assert.deepEqual(calls,[]);
|
||||
});
|
||||
test('metadata denial handles Daylight code and stops availability request',async()=>{
|
||||
const {vm,calls}=setup({metadata:{success:false,code:'NO_PERMISSION'}});
|
||||
await vm.loadPropertiesRoomTypes();
|
||||
assert.equal(vm.calendarNoPermission,true);
|
||||
assert.equal(vm.calendarReady,false);
|
||||
assert.deepEqual(calls,['settings','metadata']);
|
||||
});
|
||||
test('empty property list is reported without accessing first element',async()=>{
|
||||
const {vm,calls,toasts}=setup({metadata:{success:true,propertyList:[]}});
|
||||
await vm.loadPropertiesRoomTypes();
|
||||
assert.equal(vm.calendarReady,false);
|
||||
assert.deepEqual(calls,['settings','metadata']);
|
||||
assert.equal(toasts[0],'No calendar properties configured');
|
||||
});
|
||||
test('initial availability denial does not re-enable the grid',async()=>{
|
||||
const {vm}=setup({availability:async()=>({success:false,errorCode:'NO_PERMISSION'})});
|
||||
await vm.loadPropertiesRoomTypes();
|
||||
assert.equal(vm.calendarNoPermission,true);
|
||||
assert.equal(vm.calendarReady,false);
|
||||
});
|
||||
test('older availability response cannot overwrite a newer selection',async()=>{
|
||||
const pending=[];
|
||||
const {vm}=setup({availability:()=>new Promise(resolve=>pending.push(resolve))});
|
||||
vm.propertyList=[{code:'Macau',roomTypes:[{code:'SUITE'}]}];
|
||||
vm.selectedPropertyCode='Macau';vm.selectedRoomTypeCodes=['SUITE'];
|
||||
vm.buildCalendar();
|
||||
const first=vm.loadAvailabilityData();
|
||||
const second=vm.loadAvailabilityData();
|
||||
const date=vm.getCalendarDateRange().startDate;
|
||||
pending[1]({success:true,data:[{date,roomType:'SUITE',roomCount:2}]});
|
||||
await second;
|
||||
pending[0]({success:true,data:[{date,roomType:'SUITE',roomCount:9}]});
|
||||
await first;
|
||||
assert.equal(vm.availabilityMap[date+'_SUITE'].count,2);
|
||||
});
|
||||
test('OTHER request sends real hotel codes and deduplicated room types',()=>{
|
||||
const {vm}=setup();
|
||||
vm.propertyList=[{code:'OTHER',otherProperties:[
|
||||
{code:'A',roomTypes:[{code:'SUITE'}]},{code:'B',roomTypes:[{code:'SUITE'}]}
|
||||
]}];
|
||||
vm.selectedPropertyCode='OTHER';vm.selectedOtherPropertyCodes=['A','B'];
|
||||
assert.deepEqual(vm.buildAvailabilityParams({startDate:'2026-09-01',endDate:'2026-09-02'}),
|
||||
{Property:'A,B',RoomType:'SUITE',StartDate:'2026-09-01',EndDate:'2026-09-02'});
|
||||
});
|
||||
test('room selection cap retains existing selection',()=>{
|
||||
const {vm}=setup();
|
||||
vm.maxSelectedRoomTypes=1;vm.selectedRoomTypeCodes=['A'];
|
||||
vm.toggleRoomType('B');
|
||||
assert.deepEqual(vm.selectedRoomTypeCodes,['A']);
|
||||
});
|
||||
test('login remains launch page and calendar/settings labels have translations',async()=>{
|
||||
const raw=await readFile(new URL('../pages.json',import.meta.url),'utf8');
|
||||
const routes=JSON.parse(raw.replace(/^\s*\/\/.*$/gm,''));
|
||||
assert.equal(routes.pages[0].path,'pages/login/login');
|
||||
assert.deepEqual(routes.tabBar.list.map(t=>t.pagePath),[
|
||||
'pages/dashboard/dashboard','salessupport/todoList/todoList','pages/findPlayer/findPlayer',
|
||||
'pages/roomCalendar/roomCalendar','pages/setting/setting']);
|
||||
assert.equal(routes.tabBar.list[3].visible,false);
|
||||
for(const locale of ['en','zh-Hant']){
|
||||
const messages=JSON.parse(await readFile(new URL('../locale/'+locale+'.json',import.meta.url),'utf8'));
|
||||
assert.ok(messages['roomCalendar.title']);
|
||||
assert.ok(messages['roomCalendar.maxSelectedRoomTypes']);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user