
/* /web/static/tests/legacy/ignore_missing_deps_start.js */
window.__odooIgnoreMissingDependencies=true;;

/* /base/static/tests/test_ir_model_fields_translation.js */
odoo.define('@base/../tests/test_ir_model_fields_translation',['@web/core/registry','@web_tour/tour_utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_utils");function checkLoginColumn(translation){return[stepUtils.showAppsMenuItem(),{content:"Settings",trigger:'a[data-menu-xmlid="base.menu_administration"]',run:'click',},{content:"Open Users & Companies",trigger:'[data-menu-xmlid="base.menu_users"]',run:"click",},{content:"Open Users",trigger:'[data-menu-xmlid="base.menu_action_res_users"]',run:"click",},{content:`Login column should be ${translation}`,trigger:`[data-name="login"] span:contains("${translation}")`,}]}
registry.category("web_tour.tours").add('ir_model_fields_translation_en_tour',{url:'/odoo',steps:()=>checkLoginColumn('Login')});registry.category("web_tour.tours").add('ir_model_fields_translation_en_tour2',{url:'/odoo',steps:()=>checkLoginColumn('Login2')});registry.category("web_tour.tours").add('ir_model_fields_translation_fr_tour',{url:'/odoo',steps:()=>checkLoginColumn('Identifiant')});registry.category("web_tour.tours").add('ir_model_fields_translation_fr_tour2',{url:'/odoo',steps:()=>checkLoginColumn('Identifiant2')});return __exports;});;

/* /web/static/tests/legacy/helpers/cleanup.js */
odoo.define('@web/../tests/legacy/helpers/cleanup',[],function(require){'use strict';let __exports={};const cleanups=[];__exports.registerCleanup=registerCleanup;function registerCleanup(callback){cleanups.push(callback);}
if(window.QUnit){QUnit.on("OdooAfterTestHook",(info)=>{if(QUnit.config.debug){return;}
let cleanup;while((cleanup=cleanups.pop())){try{cleanup(info);}catch(error){console.error(error);}}});const validElements=[{tagName:"DIV",attr:"id",value:"qunit",keep:true},{tagName:"DIV",attr:"id",value:"qunit-fixture",keep:true},{tagName:"SCRIPT",attr:"id",value:""},{tagName:"DIV",attr:"class",value:"o_notification_manager"},{tagName:"DIV",attr:"class",value:"tooltip fade bs-tooltip-auto"},{tagName:"DIV",attr:"class",value:"tooltip fade bs-tooltip-auto show"},{tagName:"DIV",attr:"class",value:"tooltip tooltip-field-info fade bs-tooltip-auto"},{tagName:"DIV",attr:"class",value:"tooltip tooltip-field-info fade bs-tooltip-auto show",},{tagName:"DIV",attr:"class",value:"ui-helper-hidden-accessible"},{tagName:"UL",attr:"class",value:"ui-menu ui-widget ui-widget-content ui-autocomplete ui-front",},{tagName:"UL",attr:"class",value:"ui-menu ui-widget ui-widget-content ui-autocomplete dropdown-menu ui-front",},];QUnit.on("OdooAfterTestHook",function(info){if(QUnit.config.debug){return;}
const failed=info.testReport.getStatus()==="failed";const toRemove=[];for(const bodyChild of document.body.children){const tolerated=validElements.find((e)=>e.tagName===bodyChild.tagName&&bodyChild.getAttribute(e.attr)===e.value);if(!failed&&!tolerated){QUnit.pushFailure(`Body still contains undesirable elements:\n${bodyChild.outerHTML}`);}
if(!tolerated||!tolerated.keep){toRemove.push(bodyChild);}}
const qunitFixture=document.getElementById("qunit-fixture");if(qunitFixture.children.length){toRemove.push(...qunitFixture.children);}
for(const el of toRemove){el.remove();}
document.body.classList.remove("modal-open");});}
return __exports;});odoo.define(`@web/../tests/helpers/cleanup`,['@web/../tests/legacy/helpers/cleanup'],function(require){return require('@web/../tests/legacy/helpers/cleanup');});;

/* /web/static/tests/legacy/helpers/utils.js */
odoo.define('@web/../tests/legacy/helpers/utils',['@web/core/templates','@web/core/browser/browser','@web/core/browser/feature_detection','@web/core/network/download','@web/core/popover/popover','@web/core/utils/concurrency','@web/core/utils/patch','@web/core/utils/ui','@web/core/l10n/translation','@web/../tests/legacy/helpers/cleanup','@web/env','@odoo/owl'],function(require){'use strict';let __exports={};const{getTemplate}=require("@web/core/templates");const{browser}=require("@web/core/browser/browser");const{isMacOS}=require("@web/core/browser/feature_detection");const{download}=require("@web/core/network/download");const{getPopoverForTarget}=require("@web/core/popover/popover");const{Deferred}=require("@web/core/utils/concurrency");const{patch}=require("@web/core/utils/patch");const{isVisible}=require("@web/core/utils/ui");const{appTranslateFn}=require("@web/core/l10n/translation");const _t=(str,...args)=>appTranslateFn(str,"web",...args);const{registerCleanup}=require("@web/../tests/legacy/helpers/cleanup");const{customDirectives,globalValues}=require("@web/env");const{App,onError,onMounted,onPatched,onRendered,onWillDestroy,onWillPatch,onWillRender,onWillStart,onWillUnmount,onWillUpdateProps,useComponent,}=require("@odoo/owl");__exports.patchDate=patchDate;function patchDate(year,month,day,hours,minutes,seconds,ms=0){var RealDate=window.Date;var actualDate=new RealDate();var fakeDate=new RealDate(year,month,day,hours,minutes,seconds,ms);if(!(luxon.Settings.defaultZone instanceof luxon.FixedOffsetZone)){throw new Error("luxon.Settings.defaultZone must be a FixedOffsetZone");}
const browserOffset=-fakeDate.getTimezoneOffset();const patchedOffset=luxon.Settings.defaultZone.offset();const offsetDiff=patchedOffset-browserOffset;const correctedMinutes=fakeDate.getMinutes()-offsetDiff;fakeDate.setMinutes(correctedMinutes);var timeInterval=actualDate.getTime()-fakeDate.getTime();window.Date=(function(NativeDate){function Date(Y,M,D,h,m,s,ms){var length=arguments.length;let date;if(arguments.length>0){date=length==1&&String(Y)===Y?new NativeDate(Date.parse(Y)):length>=7?new NativeDate(Y,M,D,h,m,s,ms):length>=6?new NativeDate(Y,M,D,h,m,s):length>=5?new NativeDate(Y,M,D,h,m):length>=4?new NativeDate(Y,M,D,h):length>=3?new NativeDate(Y,M,D):length>=2?new NativeDate(Y,M):length>=1?new NativeDate(Y):new NativeDate();date.constructor=Date;return date;}else{date=new NativeDate();var time=date.getTime();time-=timeInterval;date.setTime(time);return date;}}
for(var key in NativeDate){Date[key]=NativeDate[key];}
Date.now=function(){var date=new NativeDate();var time=date.getTime();time-=timeInterval;return time;};Date.UTC=NativeDate.UTC;Date.prototype=NativeDate.prototype;Date.prototype.constructor=Date;Date.parse=NativeDate.parse;return Date;})(Date);registerCleanup(()=>{window.Date=RealDate;});}
__exports.patchTimeZone=patchTimeZone;function patchTimeZone(offset){patchWithCleanup(luxon.Settings,{defaultZone:luxon.FixedOffsetZone.instance(offset)});}
__exports.patchWithCleanup=patchWithCleanup;function patchWithCleanup(obj,patchValue){const unpatch=patch(obj,patchValue);registerCleanup(()=>{unpatch();});}
__exports.getFixture=getFixture;function getFixture(){if(!window.QUnit){return document;}
if(QUnit.config.debug){return document.body;}else{return document.getElementById("qunit-fixture");}}
__exports.nextTick=nextTick;async function nextTick(){await new Promise((resolve)=>window.requestAnimationFrame(resolve));await new Promise((resolve)=>setTimeout(resolve));}
__exports.makeDeferred=makeDeferred;function makeDeferred(){return new Deferred();}
__exports.findElement=findElement;function findElement(el,selector){let target=el;if(selector){const els=el.querySelectorAll(selector);if(els.length===0){throw new Error(`No element found (selector: ${selector})`);}
if(els.length>1){throw new Error(`Found ${els.length} elements, instead of 1 (selector: ${selector})`);}
target=els[0];}
return target;}
const mapBubblingEvent=(args)=>({...args,bubbles:true});const mapNonBubblingEvent=(args)=>({...args,bubbles:false});const mapBubblingPointerEvent=(args={})=>({clientX:args.pageX,clientY:args.pageY,...args,bubbles:true,cancelable:true,view:window,});const mapNonBubblingPointerEvent=(args)=>({...mapBubblingPointerEvent(args),bubbles:false,cancelable:false,});const mapCancelableTouchEvent=(args={})=>({...args,bubbles:true,cancelable:true,composed:true,rotation:0.0,touches:args.touches?[...args.touches.map((e)=>new Touch(e))]:undefined,view:window,zoom:1.0,});const mapNonCancelableTouchEvent=(args)=>({...mapCancelableTouchEvent(args),cancelable:false,});const mapKeyboardEvent=(args)=>({...args,bubbles:true,cancelable:true,});const getEventConstructor=(eventType)=>{switch(eventType){case"auxclick":case"click":case"contextmenu":case"dblclick":case"mousedown":case"mouseup":case"mousemove":case"mouseover":case"mouseout":{return[MouseEvent,mapBubblingPointerEvent];}
case"mouseenter":case"mouseleave":{return[MouseEvent,mapNonBubblingPointerEvent];}
case"pointerdown":case"pointerup":case"pointermove":case"pointerover":case"pointerout":{return[PointerEvent,mapBubblingPointerEvent];}
case"pointerenter":case"pointerleave":{return[PointerEvent,mapNonBubblingPointerEvent];}
case"focusin":{return[FocusEvent,mapBubblingEvent];}
case"focus":case"blur":{return[FocusEvent,mapNonBubblingEvent];}
case"cut":case"copy":case"paste":{return[ClipboardEvent,mapBubblingEvent];}
case"keydown":case"keypress":case"keyup":{return[KeyboardEvent,mapKeyboardEvent];}
case"drag":case"dragend":case"dragenter":case"dragstart":case"dragleave":case"dragover":case"drop":{return[DragEvent,mapBubblingEvent];}
case"input":{return[InputEvent,mapBubblingEvent];}
case"compositionstart":case"compositionend":{return[CompositionEvent,mapBubblingEvent];}
case"scroll":{return[UIEvent,mapNonBubblingEvent];}
case"touchstart":case"touchend":case"touchmove":{return[TouchEvent,mapCancelableTouchEvent];}
case"touchcancel":{return[TouchEvent,mapNonCancelableTouchEvent];}
default:{return[Event,mapBubblingEvent];}}};__exports.triggerEvent=triggerEvent;function triggerEvent(el,selector,eventType,eventInit,options={}){const errors=[];const target=findElement(el,selector);if(typeof eventType!=="string"){errors.push("event type must be a string");}
if(!target){errors.push("cannot find target");}else if(!options.skipVisibilityCheck&&!isVisible(target)){errors.push("target is not visible");}
if(errors.length){throw new Error(`Cannot trigger event${eventType ? `"${eventType}"` : ""}${
                selector ? `(with selector"${selector}")` : ""
            }: ${errors.join(" and ")}`);}
const[Constructor,processParams]=getEventConstructor(eventType);const event=new Constructor(eventType,processParams(eventInit));target.dispatchEvent(event);if(window.QUnit&&QUnit.config.debug){const group=`%c[${event.type.toUpperCase()}]`;console.groupCollapsed(group,"color: #b52c9b");console.log(target,event);console.groupEnd(group,"color: #b52c9b");}
if(options.sync){return event;}else{return nextTick().then(()=>event);}}
__exports.triggerEvents=triggerEvents;function triggerEvents(el,selector,eventDefs,options={}){const events=[...eventDefs].map((eventDef)=>{const[eventType,eventInit]=Array.isArray(eventDef)?eventDef:[eventDef,{}];return triggerEvent(el,selector,eventType,eventInit,options);});if(options.sync){return events;}else{return nextTick().then(()=>events);}}
__exports.triggerScroll=triggerScroll;async function triggerScroll(target,coordinates={left:null,top:null},canPropagate=true){const isScrollable=(target.scrollHeight>target.clientHeight&&target.clientHeight>0)||(target.scrollWidth>target.clientWidth&&target.clientWidth>0);if(!isScrollable&&!canPropagate){return;}
if(isScrollable){const canScrollFrom={left:coordinates.left>target.scrollLeft?target.scrollLeft+target.clientWidth<target.scrollWidth:target.scrollLeft>0,top:coordinates.top>target.scrollTop?target.scrollTop+target.clientHeight<target.scrollHeight:target.scrollTop>0,};const scrollCoordinates={};Object.entries(coordinates).forEach(([key,value])=>{if(value!==null&&canScrollFrom[key]){scrollCoordinates[key]=value;delete coordinates[key];}});target.scrollTo(scrollCoordinates);await triggerEvent(target,null,"scroll");if(!canPropagate||!Object.entries(coordinates).length){return;}}
target.parentElement?triggerScroll(target.parentElement,coordinates):triggerEvent(window,null,"scroll");await nextTick();}
__exports.click=click;function click(el,selector,{mouseEventInit={},skipDisabledCheck=false,skipVisibilityCheck=false}={}){if(!skipDisabledCheck&&el.disabled){throw new Error("Can't click on a disabled button");}
return triggerEvents(el,selector,["pointerdown","mousedown","focus","focusin","pointerup","mouseup",["click",mouseEventInit],],{skipVisibilityCheck});}
__exports.clickCreate=clickCreate;function clickCreate(htmlElement){if(htmlElement.querySelectorAll(".o_control_panel_main_buttons .o_form_button_create").length){return click(htmlElement,".o_control_panel_main_buttons .o_form_button_create");}else if(htmlElement.querySelectorAll(".o_control_panel_main_buttons .o_list_button_create").length){return click(htmlElement,".o_control_panel_main_buttons .o_list_button_create");}else{throw new Error("No edit button found to be clicked.");}}
__exports.clickEdit=clickEdit;function clickEdit(htmlElement){if(htmlElement.querySelectorAll(".o_list_button_edit").length){return click(htmlElement,".o_list_button_edit");}else{throw new Error("No edit button found to be clicked.");}}
__exports.clickSave=clickSave;async function clickSave(htmlElement){if(htmlElement.querySelectorAll(".o_form_status_indicator").length){await mouseEnter(htmlElement,".o_form_status_indicator");}
if(htmlElement.querySelectorAll(".o_form_button_save").length){return click(htmlElement,".o_form_button_save");}
const listSaveButtons=htmlElement.querySelectorAll(".o_list_button_save");if(listSaveButtons.length){return listSaveButtons.length>=2?click(listSaveButtons[1]):click(listSaveButtons[0]);}else{throw new Error("No save button found to be clicked.");}}
__exports.clickDiscard=clickDiscard;async function clickDiscard(htmlElement){if(htmlElement.querySelectorAll(".o_form_status_indicator").length){await mouseEnter(htmlElement,".o_form_status_indicator");}
if(htmlElement.querySelectorAll(".o_form_button_cancel").length){return click(htmlElement,".o_form_button_cancel");}else if($(htmlElement).find(".o_list_button_discard:visible").length){return click($(htmlElement).find(".o_list_button_discard:visible").get(0));}else{throw new Error("No discard button found to be clicked.");}}
__exports.mouseEnter=mouseEnter;async function mouseEnter(el,selector,coordinates){const target=el.querySelector(selector)||el;const atPos=coordinates||{clientX:target.getBoundingClientRect().left+target.getBoundingClientRect().width/2,clientY:target.getBoundingClientRect().top+target.getBoundingClientRect().height/2,};return triggerEvents(target,null,["pointerenter","mouseenter"],atPos);}
__exports.mouseLeave=mouseLeave;async function mouseLeave(el,selector){const target=el.querySelector(selector)||el;return triggerEvents(target,null,["pointerleave","mouseleave"]);}
__exports.editInput=editInput;async function editInput(el,selector,value){const input=findElement(el,selector);if(!(input instanceof HTMLInputElement||input instanceof HTMLTextAreaElement)){throw new Error("Only 'input' and 'textarea' elements can be edited with 'editInput'.");}
if(!["text","textarea","email","search","color","number","file","tel"].includes(input.type)){throw new Error(`Type "${input.type}" not supported by 'editInput'.`);}
const eventOpts={};if(input.type==="file"){const files=Array.isArray(value)?value:[value];const dataTransfer=new DataTransfer();for(const file of files){if(!(file instanceof File)){throw new Error(`File input value should be one or several File objects.`);}
dataTransfer.items.add(file);}
input.files=dataTransfer.files;eventOpts.skipVisibilityCheck=true;}else{input.value=value;}
await triggerEvents(input,null,["input","change"],eventOpts);if(input.type==="file"){await nextTick();await nextTick();}}
__exports.editSelect=editSelect;function editSelect(el,selector,value){const select=findElement(el,selector);if(select.tagName!=="SELECT"){throw new Error("Only select tag can be edited with selectInput.");}
select.value=value;return triggerEvent(select,null,"change");}
__exports.editSelectMenu=editSelectMenu;async function editSelectMenu(el,selector,value){const dropdown=el.querySelector(selector);await click(dropdown.querySelector(".dropdown-toggle"));for(const item of Array.from(el.querySelectorAll(".o_select_menu_menu .dropdown-item"))){if(item.textContent===value){return click(item);}}}
__exports.triggerHotkey=triggerHotkey;async function triggerHotkey(hotkey,addOverlayModParts=false,eventAttrs={}){eventAttrs.key=hotkey.split("+").pop();if(/shift/i.test(hotkey)){eventAttrs.shiftKey=true;}
if(/control/i.test(hotkey)){if(isMacOS()){eventAttrs.metaKey=true;}else{eventAttrs.ctrlKey=true;}}
if(/alt/i.test(hotkey)||addOverlayModParts){if(isMacOS()){eventAttrs.ctrlKey=true;}else{eventAttrs.altKey=true;}}
if(!("bubbles"in eventAttrs)){eventAttrs.bubbles=true;}
const[keydownEvent,keyupEvent]=await triggerEvents(document.activeElement,null,[["keydown",eventAttrs],["keyup",eventAttrs],],{skipVisibilityCheck:true});return{keydownEvent,keyupEvent};}
__exports.mockDownload=mockDownload;function mockDownload(cb){patchWithCleanup(download,{_download:cb});}
const hushConsole=__exports.hushConsole=Object.create(null);for(const propName of Object.keys(window.console)){hushConsole[propName]=()=>{};}
__exports.mockSendBeacon=mockSendBeacon;function mockSendBeacon(mock){patchWithCleanup(navigator,{sendBeacon:(url,blob)=>{return mock(url,blob)!==false;},});}
__exports.mockTimeout=mockTimeout;function mockTimeout(){const timeouts=new Map();let currentTime=0;let id=1;patchWithCleanup(browser,{setTimeout(fn,delay=0){timeouts.set(id,{fn,scheduledFor:delay+currentTime,id});return id++;},clearTimeout(id){timeouts.delete(id);},});return{execRegisteredTimeouts(){for(const{fn}of timeouts.values()){fn();}
timeouts.clear();},async advanceTime(duration){await nextTick();currentTime+=duration;for(const{fn,scheduledFor,id}of timeouts.values()){if(scheduledFor<=currentTime){fn();timeouts.delete(id);}}
await nextTick();},};}
__exports.mockAnimationFrame=mockAnimationFrame;function mockAnimationFrame(){const callbacks=new Map();let currentTime=0;let id=1;patchWithCleanup(browser,{requestAnimationFrame(fn){callbacks.set(id,{fn,scheduledFor:16+currentTime,id});return id++;},cancelAnimationFrame(id){callbacks.delete(id);},performance:{now:()=>currentTime},});return{execRegisteredAnimationFrames(){for(const{fn}of callbacks.values()){fn(currentTime);}
callbacks.clear();},async advanceFrame(count=1){await nextTick();currentTime+=16*count;for(const{fn,scheduledFor,id}of callbacks.values()){if(scheduledFor<=currentTime){fn(currentTime);callbacks.delete(id);}}
await nextTick();},};}
__exports.mount=mount;async function mount(Comp,target,config={}){let{props,env}=config;env=env||{};const configuration={env,getTemplate,test:true,props,customDirectives,globalValues,};if(env.services&&"localization"in env.services){configuration.translateFn=_t;}
const app=new App(Comp,configuration);registerCleanup(()=>app.destroy());return app.mount(target);}
__exports.destroy=destroy;function destroy(comp){comp.__owl__.app.destroy();}
__exports.findChildren=findChildren;function findChildren(comp,predicate=(e)=>e){const queue=[];[].unshift.apply(queue,Object.values(comp.__owl__.children));while(queue.length>0){const curNode=queue.pop();if(predicate(curNode)){return curNode;}
[].unshift.apply(queue,Object.values(curNode.component.__owl__.children));}}
__exports.useChild=useChild;function useChild(){const node=useComponent().__owl__;const setChild=()=>{const componentNode=Object.values(node.children)[0];node.component.child=componentNode.component;};onMounted(setChild);onPatched(setChild);}
__exports.useLogLifeCycle=useLogLifeCycle;function useLogLifeCycle(logFn,name=""){const component=useComponent();let loggedName=`${component.constructor.name}`;if(name){loggedName=`${component.constructor.name} ${name}`;}
onError(()=>{logFn(`onError ${loggedName}`);});onMounted(()=>{logFn(`onMounted ${loggedName}`);});onPatched(()=>{logFn(`onPatched ${loggedName}`);});onRendered(()=>{logFn(`onRendered ${loggedName}`);});onWillDestroy(()=>{logFn(`onWillDestroy ${loggedName}`);});onWillPatch(()=>{logFn(`onWillPatch ${loggedName}`);});onWillRender(()=>{logFn(`onWillRender ${loggedName}`);});onWillStart(()=>{logFn(`onWillStart ${loggedName}`);});onWillUnmount(()=>{logFn(`onWillUnmount ${loggedName}`);});onWillUpdateProps(()=>{logFn(`onWillUpdateProps ${loggedName}`);});}
function getDifferentParents(n1,n2){const parents=[n2];while(parents[0].parentNode){const parent=parents[0].parentNode;if(parent.contains(n1)){break;}
parents.unshift(parent);}
return parents;}
__exports.dragAndDrop=dragAndDrop;async function dragAndDrop(from,to,position){const{drop}=await drag(from);await drop(to,position);}
__exports.drag=drag;async function drag(from,pointerType="mouse"){const assertIsDragging=(fn,endDrag)=>{return{async[fn.name](...args){if(dragEndReason){throw new Error(`Cannot execute drag helper '${fn.name}': drag sequence has been ended by '${dragEndReason}'.`);}
await fn(...args);if(endDrag){dragEndReason=fn.name;}},}[fn.name];};const cancel=assertIsDragging(async function cancel(){await triggerEvent(window,null,"keydown",{key:"Escape"});},true);const drop=assertIsDragging(async function drop(to,position){if(to){await moveTo(to,position);}
await triggerEvent(target||source,null,"pointerup",targetPosition);},true);const getEl=(selector)=>selector instanceof Element?selector:fixture.querySelector(selector);const getTargetPosition=(position)=>{const tRect=target.getBoundingClientRect();const tPos={clientX:Math.floor(tRect.x),clientY:Math.floor(tRect.y),};if(position&&typeof position==="object"){tPos.clientX+=position.x||0;tPos.clientY+=position.y||0;}else{const positions=typeof position==="string"?position.split("-"):[];if(positions.includes("left")){tPos.clientX-=1;}else if(positions.includes("right")){tPos.clientX+=Math.ceil(tRect.width)+1;}else{tPos.clientX+=Math.floor(tRect.width/2);}
if(positions.includes("top")){tPos.clientY-=1;}else if(positions.includes("bottom")){tPos.clientY+=Math.ceil(tRect.height)+1;}else{tPos.clientY+=Math.floor(tRect.height/2);}}
return tPos;};const moveTo=assertIsDragging(async function moveTo(to,position){target=getEl(to);if(!target){return;}
targetPosition=getTargetPosition(position);await triggerEvent(source,null,"pointermove",{...targetPosition,button:-1});for(const parent of getDifferentParents(source,target)){triggerEvent(parent,null,"pointerenter",targetPosition);}
await nextTick();return dragHelpers;},false);const dragHelpers={cancel,drop,moveTo};const fixture=getFixture();const source=getEl(from instanceof Element?from:fixture.querySelector(from));const sourceRect=source.getBoundingClientRect();let dragEndReason=null;let target;let targetPosition;await triggerEvent(source,null,"pointerdown",{pointerType,clientX:sourceRect.x+sourceRect.width/2,clientY:sourceRect.y+sourceRect.height/2,});return dragHelpers;}
__exports.getDropdownMenu=getDropdownMenu;function getDropdownMenu(target,togglerSelector){if(!(target instanceof HTMLElement)){throw new Error(`getDropdownMenu: target is not an HTMLElement.`);}
let el=togglerSelector instanceof HTMLElement?togglerSelector:target.querySelector(togglerSelector);if(el&&!el.classList.contains("o-dropdown")){el=el.querySelector(".o-dropdown");}
if(!el){throw new Error(`getDropdownMenu: Could not find element "${togglerSelector}".`);}
return getPopoverForTarget(el);}
__exports.clickDropdown=clickDropdown;async function clickDropdown(target,fieldName){const dropdownInput=target.querySelector(`[name='${fieldName}'] .dropdown input`);dropdownInput.focus();await nextTick();await click(dropdownInput);}
__exports.clickOpenedDropdownItem=clickOpenedDropdownItem;async function clickOpenedDropdownItem(target,fieldName,itemContent){const dropdowns=target.querySelectorAll(`[name='${fieldName}'] .dropdown .dropdown-menu`);if(dropdowns.length===0){throw new Error(`No dropdown found for field ${fieldName}`);}else if(dropdowns.length>1){throw new Error(`Found ${dropdowns.length} dropdowns for field ${fieldName}`);}
const dropdownItems=dropdowns[0].querySelectorAll("li");const indexToClick=Array.from(dropdownItems).map((html)=>html.textContent).indexOf(itemContent);if(indexToClick===-1){throw new Error(`The element '${itemContent}' does not exist in the dropdown`);}
await click(dropdownItems[indexToClick]);}
__exports.selectDropdownItem=selectDropdownItem;async function selectDropdownItem(target,fieldName,itemContent){await clickDropdown(target,fieldName);await clickOpenedDropdownItem(target,fieldName,itemContent);}
__exports.getNodesTextContent=getNodesTextContent;function getNodesTextContent(nodes){return Array.from(nodes).map((n)=>n.textContent);}
__exports.clickOpenM2ODropdown=clickOpenM2ODropdown;async function clickOpenM2ODropdown(el,fieldName,selector){const m2oSelector=`${selector || ""} .o_field_many2one[name=${fieldName}] input`;const matches=el.querySelectorAll(m2oSelector);if(matches.length!==1){throw new Error(`cannot open m2o: selector ${selector} has been found ${matches.length} instead of 1`);}
await click(matches[0]);return matches[0];}
__exports.clickM2OHighlightedItem=clickM2OHighlightedItem;async function clickM2OHighlightedItem(el,fieldName,selector){const m2oSelector=`${selector || ""} .o_field_many2one[name=${fieldName}] input`;const matches=el.querySelectorAll(m2oSelector);if(matches.length!==1){throw new Error(`cannot open m2o: selector ${selector} has been found ${matches.length} instead of 1`);}
return click(matches[0].parentElement.querySelector("li"));}
__exports.addRow=addRow;async function addRow(target,selector){await click(target.querySelector(`${selector ? selector : ""} .o_field_x2many_list_row_add a`));}
__exports.removeRow=removeRow;async function removeRow(target,index){await click(target.querySelectorAll(".o_list_record_remove")[index]);}
return __exports;});odoo.define(`@web/../tests/helpers/utils`,['@web/../tests/legacy/helpers/utils'],function(require){return require('@web/../tests/legacy/helpers/utils');});;

/* /web/static/tests/legacy/utils.js */
odoo.define('@web/../tests/legacy/utils',['@web/core/utils/ui','@web/../tests/helpers/cleanup','@web/../tests/helpers/utils'],function(require){'use strict';let __exports={};const{isVisible}=require("@web/core/utils/ui");const{registerCleanup}=require("@web/../tests/helpers/cleanup");const{click:webClick,getFixture,makeDeferred,triggerEvents:webTriggerEvents,}=require("@web/../tests/helpers/utils");function createFakeDataTransfer(files){return{dropEffect:"all",effectAllowed:"all",files,items:[],types:["Files"],};}
__exports.click=click;async function click(selector,options={}){const{shiftKey}=options;delete options.shiftKey;await contains(selector,{click:{shiftKey},...options});}
__exports.dragenterFiles=dragenterFiles;async function dragenterFiles(selector,files,options){await contains(selector,{dragenterFiles:files,...options});}
__exports.dragoverFiles=dragoverFiles;async function dragoverFiles(selector,files,options){await contains(selector,{dragoverFiles:files,...options});}
__exports.dropFiles=dropFiles;async function dropFiles(selector,files,options){await contains(selector,{dropFiles:files,...options});}
__exports.inputFiles=inputFiles;async function inputFiles(selector,files,options){await contains(selector,{inputFiles:files,...options});}
__exports.pasteFiles=pasteFiles;async function pasteFiles(selector,files,options){await contains(selector,{pasteFiles:files,...options});}
__exports.focus=focus;async function focus(selector,options){await contains(selector,{setFocus:true,...options});}
__exports.insertText=insertText;async function insertText(selector,content,options={}){const{replace=false}=options;delete options.replace;await contains(selector,{...options,insertText:{content,replace}});}
__exports.scroll=scroll;async function scroll(selector,scrollTop,options){await contains(selector,{setScroll:scrollTop,...options});}
__exports.triggerEvents=triggerEvents;async function triggerEvents(selector,events,options){await contains(selector,{triggerEvents:events,...options});}
function log(ok,message){if(window.QUnit){QUnit.assert.ok(ok,message);}else{if(ok){console.log(message);}else{console.error(message);}}}
let hasUsedContainsPositively=false;if(window.QUnit){QUnit.testStart(()=>(hasUsedContainsPositively=false));}
class Contains{constructor(selector,options={}){this.selector=selector;this.options=options;this.options.count??=1;this.options.targetParam=this.options.target;this.options.target??=getFixture();let selectorMessage=`${this.options.count} of "${this.selector}"`;if(this.options.visible!==undefined){selectorMessage=`${selectorMessage} ${
                this.options.visible ? "visible" : "invisible"
            }`;}
if(this.options.targetParam){selectorMessage=`${selectorMessage} inside a specific target`;}
if(this.options.parent){selectorMessage=`${selectorMessage} inside a specific parent`;}
if(this.options.contains){selectorMessage=`${selectorMessage} with a specified sub-contains`;}
if(this.options.text!==undefined){selectorMessage=`${selectorMessage} with text "${this.options.text}"`;}
if(this.options.textContent!==undefined){selectorMessage=`${selectorMessage} with textContent "${this.options.textContent}"`;}
if(this.options.value!==undefined){selectorMessage=`${selectorMessage} with value "${this.options.value}"`;}
if(this.options.scroll!==undefined){selectorMessage=`${selectorMessage} with scroll "${this.options.scroll}"`;}
if(this.options.after!==undefined){selectorMessage=`${selectorMessage} after a specified element`;}
if(this.options.before!==undefined){selectorMessage=`${selectorMessage} before a specified element`;}
this.selectorMessage=selectorMessage;if(this.options.contains&&!Array.isArray(this.options.contains[0])){this.options.contains=[this.options.contains];}
if(this.options.count){hasUsedContainsPositively=true;}else if(!hasUsedContainsPositively){throw new Error(`Starting a test with "contains" of count 0 for selector "${this.selector}" is useless because it might immediately resolve. Start the test by checking that an expected element actually exists.`);}
this.successMessage=undefined;this.executeError=undefined;}
run(){this.done=false;this.def=makeDeferred();this.scrollListeners=new Set();this.onScroll=()=>this.runOnce("after scroll");if(!this.runOnce("immediately")){this.timer=setTimeout(()=>this.runOnce("Timeout of 5 seconds",{crashOnFail:true}),5000);this.observer=new MutationObserver((mutations)=>{try{this.runOnce("after mutations");}catch(e){this.def.reject(e);}});this.observer.observe(this.options.target,{attributes:true,childList:true,subtree:true,});registerCleanup(()=>{if(!this.done){this.runOnce("Test ended",{crashOnFail:true});}});}
return this.def;}
runOnce(whenMessage,{crashOnFail=false,executeOnSuccess=true}={}){const res=this.select();if(res?.length===this.options.count||crashOnFail){this.observer?.disconnect();clearTimeout(this.timer);for(const el of this.scrollListeners??[]){el.removeEventListener("scroll",this.onScroll);}
this.done=true;}
if(res?.length===this.options.count){this.successMessage=`Found ${this.selectorMessage} (${whenMessage})`;if(executeOnSuccess){this.executeAction(res[0]);}
return res;}else{this.executeError=()=>{let message=`Failed to find ${this.selectorMessage} (${whenMessage}).`;message=res?`${message} Found ${res.length} instead.`:`${message} Parent not found.`;if(this.parentContains){if(this.parentContains.successMessage){log(true,this.parentContains.successMessage);}else{this.parentContains.executeError();}}
log(false,message);this.def?.reject(new Error(message));for(const childContains of this.childrenContains||[]){if(childContains.successMessage){log(true,childContains.successMessage);}else{childContains.executeError();}}};if(crashOnFail){this.executeError();}}}
executeAction(el){let message=this.successMessage;if(this.options.click){message=`${message} and clicked it`;webClick(el,undefined,{mouseEventInit:this.options.click,skipDisabledCheck:true,skipVisibilityCheck:true,});}
if(this.options.dragenterFiles){message=`${message} and dragentered ${this.options.dragenterFiles.length} file(s)`;const ev=new Event("dragenter",{bubbles:true});Object.defineProperty(ev,"dataTransfer",{value:createFakeDataTransfer(this.options.dragenterFiles),});el.dispatchEvent(ev);}
if(this.options.dragoverFiles){message=`${message} and dragovered ${this.options.dragoverFiles.length} file(s)`;const ev=new Event("dragover",{bubbles:true});Object.defineProperty(ev,"dataTransfer",{value:createFakeDataTransfer(this.options.dragoverFiles),});el.dispatchEvent(ev);}
if(this.options.dropFiles){message=`${message} and dropped ${this.options.dropFiles.length} file(s)`;const ev=new Event("drop",{bubbles:true});Object.defineProperty(ev,"dataTransfer",{value:createFakeDataTransfer(this.options.dropFiles),});el.dispatchEvent(ev);}
if(this.options.inputFiles){message=`${message} and inputted ${this.options.inputFiles.length} file(s)`;const dataTransfer=new window.DataTransfer();for(const file of this.options.inputFiles){dataTransfer.items.add(file);}
el.files=dataTransfer.files;const versionRaw=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);const chromeVersion=versionRaw?parseInt(versionRaw[2],10):false;if(!chromeVersion||chromeVersion>=73){el.dispatchEvent(new Event("change"));}}
if(this.options.insertText!==undefined){message=`${message} and inserted text "${this.options.insertText.content}" (replace: ${this.options.insertText.replace})`;el.focus();if(this.options.insertText.replace){el.value="";el.dispatchEvent(new window.KeyboardEvent("keydown",{key:"Backspace"}));el.dispatchEvent(new window.KeyboardEvent("keyup",{key:"Backspace"}));el.dispatchEvent(new window.InputEvent("input"));}
for(const char of this.options.insertText.content){el.value+=char;el.dispatchEvent(new window.KeyboardEvent("keydown",{key:char}));el.dispatchEvent(new window.KeyboardEvent("keyup",{key:char}));el.dispatchEvent(new window.InputEvent("input"));}
el.dispatchEvent(new window.InputEvent("change"));}
if(this.options.pasteFiles){message=`${message} and pasted ${this.options.pasteFiles.length} file(s)`;const ev=new Event("paste",{bubbles:true});Object.defineProperty(ev,"clipboardData",{value:createFakeDataTransfer(this.options.pasteFiles),});el.dispatchEvent(ev);}
if(this.options.setFocus){message=`${message} and focused it`;el.focus();}
if(this.options.setScroll!==undefined){message=`${message} and set scroll to "${this.options.setScroll}"`;el.scrollTop=this.options.setScroll==="bottom"?el.scrollHeight:this.options.setScroll;}
if(this.options.triggerEvents){message=`${message} and triggered "${this.options.triggerEvents.join(", ")}" events`;webTriggerEvents(el,null,this.options.triggerEvents,{skipVisibilityCheck:true,});}
if(this.parentContains){log(true,this.parentContains.successMessage);}
log(true,message);for(const childContains of this.childrenContains){log(true,childContains.successMessage);}
this.def?.resolve();}
select(){const target=this.selectParent();if(!target){return;}
const baseRes=[...target.querySelectorAll(this.selector)].map((el)=>(this.options.shadowRoot?el.shadowRoot:el)).filter((el)=>el);this.childrenContains=[];const res=baseRes.filter((el,currentIndex)=>{let condition=(this.options.textContent===undefined||el.textContent.trim()===this.options.textContent)&&(this.options.value===undefined||el.value===this.options.value)&&(this.options.scroll===undefined||(this.options.scroll==="bottom"?Math.abs(el.scrollHeight-el.clientHeight-el.scrollTop)<=1:Math.abs(el.scrollTop-this.options.scroll)<=1));if(condition&&this.options.text!==undefined){if(el.textContent.trim()!==this.options.text&&[...el.querySelectorAll("*")].every((el)=>el.textContent.trim()!==this.options.text)){condition=false;}}
if(condition&&this.options.contains){for(const param of this.options.contains){const childContains=new Contains(param[0],{...param[1],target:el});if(!childContains.runOnce(`as child of el ${currentIndex + 1})`,{executeOnSuccess:false,})){condition=false;}
this.childrenContains.push(childContains);}}
if(condition&&this.options.visible!==undefined){if(isVisible(el)!==this.options.visible){condition=false;}}
if(condition&&this.options.after){const afterContains=new Contains(this.options.after[0],{...this.options.after[1],target,});const afterEl=afterContains.runOnce(`as "after"`,{executeOnSuccess:false,})?.[0];if(!afterEl||!(el.compareDocumentPosition(afterEl)&Node.DOCUMENT_POSITION_PRECEDING)){condition=false;}
this.childrenContains.push(afterContains);}
if(condition&&this.options.before){const beforeContains=new Contains(this.options.before[0],{...this.options.before[1],target,});const beforeEl=beforeContains.runOnce(`as "before"`,{executeOnSuccess:false,})?.[0];if(!beforeEl||!(el.compareDocumentPosition(beforeEl)&Node.DOCUMENT_POSITION_FOLLOWING)){condition=false;}
this.childrenContains.push(beforeContains);}
return condition;});if(this.options.scroll!==undefined&&this.scrollListeners&&baseRes.length===this.options.count&&res.length!==this.options.count){for(const el of baseRes){if(!this.scrollListeners.has(el)){this.scrollListeners.add(el);el.addEventListener("scroll",this.onScroll);}}}
return res;}
selectParent(){if(this.options.parent){this.parentContains=new Contains(this.options.parent[0],{...this.options.parent[1],target:this.options.target,});return this.parentContains.runOnce(`as parent`,{executeOnSuccess:false})?.[0];}
return this.options.target;}}
__exports.contains=contains;async function contains(selector,options){await new Contains(selector,options).run();}
const stepState={expectedSteps:null,deferred:null,timeout:null,currentSteps:[],clear(){clearTimeout(this.timeout);this.timeout=null;this.deferred=null;this.currentSteps=[];this.expectedSteps=null;},check({crashOnFail=false}={}){const success=this.expectedSteps.length===this.currentSteps.length&&this.expectedSteps.every((s,i)=>s===this.currentSteps[i]);if(!success&&!crashOnFail){return;}
QUnit.config.current.assert.verifySteps(this.expectedSteps);if(success){this.deferred.resolve();}else{this.deferred.reject(new Error("Steps do not match."));}
this.clear();},};if(window.QUnit){QUnit.testStart(()=>registerCleanup(()=>{if(stepState.expectedSteps){stepState.check({crashOnFail:true});}else{stepState.clear();}}));}
__exports.step=step;function step(step){stepState.currentSteps.push(step);QUnit.config.current.assert.step(step);if(stepState.expectedSteps){stepState.check();}}
__exports.assertSteps=assertSteps;function assertSteps(steps){if(stepState.expectedSteps){stepState.check({crashOnFail:true});}
stepState.expectedSteps=steps;stepState.deferred=makeDeferred();stepState.timeout=setTimeout(()=>stepState.check({crashOnFail:true}),2000);stepState.check();return stepState.deferred;}
return __exports;});odoo.define(`@web/../tests/utils`,['@web/../tests/legacy/utils'],function(require){return require('@web/../tests/legacy/utils');});;

/* /web/static/tests/tours/favorite_management_tour.js */
odoo.define('@web/../tests/tours/favorite_management_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("test_favorite_management",{url:"/odoo/apps",steps:()=>[{trigger:".o_kanban_renderer:not(:has(.o_kanban_record:contains(France - Localizations)))",},{trigger:".o_facet_remove",run:"click",},{trigger:".o_kanban_renderer:has(.o_kanban_record:contains(France - Localizations))",},{trigger:".o_searchview_dropdown_toggler",run:"click",},{trigger:".o_favorite_menu .o_accordion > .o_menu_item",run:"click",},{trigger:".o_favorite_menu .o_accordion_values .o_input",run:"edit Apps1",},{trigger:".o_save_favorite",run:"click",},{trigger:".o_searchview_facet .o_facet_value:contains(Apps1)",},{trigger:".o_group_by_menu > .o-dropdown-item:contains(Category)",run:"click",},{trigger:".o_kanban_header:contains(Account Charts)",},{trigger:".o_favorite_menu .o_accordion_values .o_input",run:"edit Apps2",},{trigger:".o_save_favorite",run:"click",},{trigger:".o_favorite_menu .o-dropdown-item:contains(Apps2)",},{trigger:".o_favorite_menu .o-dropdown-item:contains(Apps1) i:not(:visible)",run:"click",},{trigger:".o_field_domain > div > div",run:"click",},{trigger:".o_tree_editor_row:contains(New Rule) > a",run:"click",},{trigger:".o_form_button_save",run:"click",},{trigger:".o_back_button > a",run:"click",},{trigger:".o_facet_values:contains('Apps2')",},{trigger:".o_kanban_header:contains(Account Charts)",},{trigger:".o_searchview_dropdown_toggler",run:"click",},{trigger:".o_favorite_menu .o-dropdown-item:contains(Apps1)",run:"click",},{trigger:".o_kanban_record:not(.o_kanban_ghost):only",},{trigger:".o_favorite_menu .o-dropdown-item:contains(Apps1) i:not(:visible)",run:"click",},{trigger:".o_form_view .o_cp_action_menus .o-dropdown",run:"click",},{trigger:".o_popover > .o-dropdown-item:contains(Delete)",run:"click",},{trigger:".o_technical_modal button:contains(Delete)",run:"click",},{trigger:".o_searchview_dropdown_toggler",run:"click",},{trigger:".o_favorite_menu .o-dropdown-item:contains(Apps2)",},{content:"There should not be any facet inside the search bar",trigger:"body:not(:has(.o_searchview_facet))",},{content:"The Apps1 filter should be deleted",trigger:"body:not(:has(.o_favorite_menu .o-dropdown-item:contains(Apps1)))",},],});return __exports;});;

/* /web/static/tests/tours/test_user_group_settings_tour.js */
odoo.define('@web/../tests/tours/test_user_group_settings_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("test_user_group_settings",{url:"/odoo/settings?debug=assets,tests",steps:()=>[{trigger:'button[data-menu-xmlid="base.menu_users"]',content:"open user menu",run:"click",},{trigger:'a[data-menu-xmlid="base.menu_action_res_groups_privilege"]',content:"open privilege menu",run:"click",},{trigger:'th.o_group_name:contains("Master Data")',},{trigger:"button.o_list_button_add",content:"click on new button",run:"click",},{trigger:'.o_field_char[name="name"] input',content:"insert a privilege name",run:"edit Privi Foo",},{trigger:".o_field_x2many_list_row_add a",content:"add groups (open modal)",run:"click",},{trigger:".o_create_button",content:"create the first group",run:"click",},{trigger:'.o_field_char[name="name"] input[placeholder="Group Name"]',content:"insert the first group name",run:"edit Bar User",},{trigger:"footer .o_form_button_save_new",content:"create the second group",run:"click",},{trigger:"body .o_notebook_content:contains(bar user)",},{trigger:'.o_field_char[name="name"] input[placeholder="Group Name"]',content:"insert the second group name",run:"edit Bar Manager",},{trigger:'a[name="inherit_groups"]',content:"get implied groups",run:"click",},{trigger:'div[name="implied_ids"] .o_field_x2many_list_row_add a',content:"switch to implied",run:"click",},{trigger:".o_searchview_input",content:"search 'Bar' groups",run:"edit Bar",},{trigger:".o_searchview_autocomplete .o-dropdown-item.focus",content:"Validate search",run:"click",},{trigger:'.o_data_cell:contains("Bar User"):last',content:"click to implied group 'Bar User'",run:"click",},{trigger:"footer .o_form_button_save",content:"save group and close modal",run:"click",},{trigger:"body:not(:has(.modal:visible)) .o_notebook_content:contains(bar user):contains(bar manager)",},{trigger:'button[data-menu-xmlid="base.menu_users"]',content:"open user menu",run:"click",},{trigger:'a[data-menu-xmlid="base.menu_action_res_users"]',content:"open users & companies menu",run:"click",},{trigger:".o_list_renderer:contains(marc demo):contains(mitchell admin)",},{trigger:'.o_data_row:contains(Marc Demo) .o_field_cell[name="name"]',content:"open users menu",run:"click",},{trigger:'.o_last_breadcrumb_item:contains("Marc Demo")',content:"check if is demo user",},{trigger:'.o_field_widget[name="group_ids"] .o_cell:has(label:contains("Privi Foo")) + .o_cell .o_select_menu input',content:"Add 'Bar Manager' access to demo user",run:`click`,},{trigger:`.o-dropdown--menu .o_select_menu_item:contains("Bar Manager")`,run:"click",},{trigger:'.o_field_widget[name="group_ids"] .o_cell:has(label:contains("Privi Foo")) + .o_cell .o_group_info_button',content:"open group information for the new group",run:"click",},{trigger:'.o_popover:contains("Privi Foo") a:contains("Bar Manager")',content:"open the group from the info button",run:"click",},{trigger:'.o_last_breadcrumb_item:contains("Bar Manager")',content:"check if is Bar Manager group",},{trigger:'.o_field_many2many[name="user_ids"] .o_data_cell:contains("Marc Demo")',content:"check if demo user has this group",},],});return __exports;});;

/* /web/static/tests/tours/user_switch_tour.js */
odoo.define('@web/../tests/tours/user_switch_tour',['@web/core/registry','@bus/workers/websocket_worker','@odoo/owl'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{WORKER_STATE}=require("@bus/workers/websocket_worker");const{whenReady}=require("@odoo/owl");function logout(){return[{trigger:".o_web_client .o_navbar",async run(){await whenReady();await new Promise((resolve)=>requestAnimationFrame(resolve));await new Promise((resolve)=>{const bus=odoo.__WOWL_DEBUG__.root.env.services.bus_service;bus.addEventListener("BUS:CONNECT",resolve,{once:true});if(bus.workerState===WORKER_STATE.CONNECTED){resolve();}});},},{content:"check we're logged in",trigger:".o_user_menu .dropdown-toggle",run:"click",},{content:"click the Log out button",trigger:".dropdown-item[data-menu=logout]",run:"click",expectUnloadPage:true,},{trigger:".oe_website_login_container, .o_database_list",},];}
registry.category("web_tour.tours").add("test_user_switch",{url:"/odoo",steps:()=>[...logout(),{content:"check if the login input is empty",trigger:"input#login:empty",},{content:"check if the password input is empty",trigger:"input#password:empty",},{content:"Should contains the user switch button",trigger:".oe_login_form .o_user_switch_btn",run:"click",},{content:"Click on Marc Demo on the quick login page",trigger:".o_user_switch:not(:has(.list-group-item:nth-child(2))) .list-group-item:contains('Marc Demo')",run:"click",},{content:"Check user choice button to back on the quick login page",trigger:".oe_login_form .o_user_switch_btn",run:"click",},{content:"Display the login form",trigger:".o_user_switch .fa-user-circle-o",run:"click",},{content:"fill the login",trigger:"input#login",run:"edit admin",},{content:"fill the password",trigger:"input#password",run:"edit admin",},{content:"click on login button",trigger:'button:contains("Log in")',run:"click",expectUnloadPage:true,},...logout(),{content:"Check if there is Mitchell Admin in user list selection",trigger:".o_user_switch .list-group-item:nth-child(1):contains('Mitchell Admin')",},{content:"Check if there is Marc Demo in user list selection",trigger:".o_user_switch .list-group-item:nth-child(2):contains('Marc Demo')",},{content:"Choice demo",trigger:".o_user_switch .list-group-item:contains('Marc Demo')",run:"click",},{content:"check the login for demo",trigger:"input#login:value('demo')",},{content:"fill the password",trigger:"input#password",run:"edit demo",},{content:"Check back button to back on the quick login page",trigger:".oe_login_form .o_user_switch_btn",run:"click",},{content:"Check have 2 users",trigger:".o_user_switch .list-group-item:nth-child(2)",},{content:"Click on Mitchell Admin",trigger:".o_user_switch .list-group-item:nth-child(1):contains('Mitchell Admin')",run:"click",},{content:"check the login for admin",trigger:"input#login:value('admin')",},{content:"fill the password",trigger:"input#password",run:"edit admin",},{content:"Check back button to back on the quick login page",trigger:".oe_login_form .o_user_switch_btn",run:"click",},{content:"Display the login form",trigger:".o_user_switch .fa-user-circle-o",run:"click",},{content:"the login form is display",trigger:"form.oe_login_form:not(.d-none)",},{content:"check if the login input is empty",trigger:"input#login:empty",},{content:"check if the password input is empty",trigger:"input#password:empty",},{content:"Back to user switch",trigger:".oe_login_form .o_user_switch_btn",run:"click",},{content:"Remove the admin user from page",trigger:".o_user_switch .d-flex:first-child .fa-times",run:"click",},{content:"only one user is left on quick login",trigger:".o_user_switch:not(:has(.list-group-item:nth-child(2))) .list-group-item:contains('Marc Demo')",},],});return __exports;});;

/* /web_tour/static/src/js/tour_automatic/tour_helpers.js */
odoo.define('@web_tour/js/tour_automatic/tour_helpers',[],function(require){'use strict';let __exports={};const TourHelpers=__exports.TourHelpers=class TourHelpers{constructor(anchor){this.anchor=anchor;this.delay=20;return new Proxy(this,{get(target,prop,receiver){const value=Reflect.get(target,prop,receiver);if(typeof value==="function"&&prop!=="constructor"){return value.bind(target);}
return value;},});}}
return __exports;});;

/* /web/static/lib/hoot-dom/helpers/dom.js */
odoo.define('@web/../lib/hoot-dom/helpers/dom',['@web/../lib/hoot-dom/hoot_dom_utils','@web/../lib/hoot-dom/helpers/time'],function(require){'use strict';let __exports={};const{getTag,isFirefox,isInstanceOf,isIterable,parseRegExp}=require("@web/../lib/hoot-dom/hoot_dom_utils");const{waitUntil}=require("@web/../lib/hoot-dom/helpers/time");const{document,DOMParser,Error,innerWidth,innerHeight,Map,Number:{isInteger:$isInteger,isNaN:$isNaN,parseInt:$parseInt,parseFloat:$parseFloat},Object:{entries:$entries,keys:$keys,values:$values},RegExp,String:{raw:$raw},window,}=globalThis;function applyFilters(filters,nodes){for(const filter of filters){const filteredGroupNodes=[];for(let i=0;i<nodes.length;i++){const result=matchFilter(filter,nodes,i);if(result===true){filteredGroupNodes.push(nodes[i]);}else if(result){filteredGroupNodes.push(result);}}
nodes=filteredGroupNodes;if(globalFilterDescriptors.has(filter)){globalFilterDescriptors.get(filter).push(nodes.length);}else if(selectorFilterDescriptors.has(filter)){selectorFilterDescriptors.get(filter).push(nodes.length);}}
return nodes;}
function compilePseudoClassRegex(){const customKeys=[...customPseudoClasses.keys()].filter((k)=>k!=="has"&&k!=="not");return new RegExp(`:(${customKeys.join("|")})`);}
function elementsMatch(elements,selector){if(!elements.length){return false;}
return parseSelector(selector).some((selectorParts)=>{const[baseSelector,...filters]=selectorParts.at(-1);for(let i=0;i<elements.length;i++){if(baseSelector&&!elements[i].matches(baseSelector)){return false;}
if(!filters.every((filter)=>matchFilter(filter,elements,i))){return false;}}
return true;});}
function ensureCount(options){options={...options};if(!("eq"in options||"first"in options||"last"in options)){options.first=true;}
return options;}
function ensureElement(node){if(node){if(isDocument(node)){return node.documentElement;}
if(isWindow(node)){return node.document.documentElement;}
if(isElement(node)){return node;}}
return null;}
function extractLayers(nodes,level,keepInlineTextNodes){const layers=[];for(const node of nodes){if(node.nodeType===Node.COMMENT_NODE){continue;}
if(node.nodeType===Node.TEXT_NODE){const textContent=node.nodeValue.replaceAll(/\n/g,"");const trimmedTextContent=textContent.trim();if(trimmedTextContent){const inline=textContent===trimmedTextContent;layers.push({inline,level,value:{textContent:trimmedTextContent}});}
continue;}
const[open,close]=node.outerHTML.replace(`>${node.innerHTML}<`,">\n<").split("\n");const layer={inline:false,level,value:{open,close}};layers.push(layer);const childLayers=extractLayers(node.childNodes,level+1,false);if(keepInlineTextNodes&&childLayers.length===1&&childLayers[0].inline){layer.value.textContent=childLayers[0].value.textContent;}else{layers.push(...childLayers);}}
return layers;}
function filterUniqueNodes(nodesToFilter){const nodes=[];for(const node of nodesToFilter){if(isQueryableNode(node)&&!nodes.includes(node)){nodes.push(node);}}
return nodes;}
function generateStringFromLayers(layers,tabSize){const result=[];let layerIndex=0;while(layers.length>0){const layer=layers[layerIndex];const{level,value}=layer;const pad=" ".repeat(tabSize*level);let nextLayerIndex=layerIndex+1;if(value.open){if(value.textContent){result.push(`${pad}${value.open}${value.textContent}${value.close}`);layers.splice(layerIndex,1);nextLayerIndex--;}else{result.push(`${pad}${value.open}`);delete value.open;}}else{if(value.close){result.push(`${pad}${value.close}`);}else if(value.textContent){result.push(`${pad}${value.textContent}`);}
layers.splice(layerIndex,1);nextLayerIndex--;}
if(nextLayerIndex>=layers.length){layerIndex=nextLayerIndex-1;continue;}
const nextLayer=layers[nextLayerIndex];if(nextLayerIndex===0||nextLayer.level>layers[nextLayerIndex-1].level){layerIndex=nextLayerIndex;}else{layerIndex=nextLayerIndex-1;}}
return result.join("\n");}
function getFiltersDescription(modifierInfo){const description=[];for(const[modifier,content,count=0]of modifierInfo){const makeLabel=MODIFIER_SUFFIX_LABELS[modifier];const elements=plural("element",count);if(typeof makeLabel==="function"){description.push(`${count} ${elements} ${makeLabel(content)}`);}else{description.push(`${count} ${modifier} ${elements}`);}
if(!count){break;}}
return description;}
function getInlineNodeText(node){return getNodeText(node,{inline:true});}
function getNodeContent(node){switch(getTag(node)){case"input":case"option":case"textarea":return getNodeValue(node);case"select":return[...node.selectedOptions].map((node)=>getNodeValue(node)).join(",");}
return getNodeText(node);}
function getNodeIframe(node){const doc=node.contentDocument;return doc&&doc.readyState!=="loading"?doc:false;}
function getNodeShadowRoot(node){return node.shadowRoot;}
function getQueryFilter(pseudoClass,content){const makeQueryFilter=customPseudoClasses.get(pseudoClass);try{return makeQueryFilter(content);}catch(err){let message=`error while parsing pseudo-class ':${pseudoClass}'`;const cause=String(err?.message||err);if(cause){message+=`: ${cause}`;}
throw new HootDomError(message);}}
function getRawValue(node){return node.value;}
function getStringContent(string){return string.match(R_QUOTE_CONTENT)?.[2]||string;}
function getWaitForMessage(){const message=`expected at least 1 element after %timeout%ms and ${lastQueryMessage}`;lastQueryMessage="";return message;}
function getWaitForNoneMessage(){const message=`expected 0 elements after %timeout%ms and ${lastQueryMessage}`;lastQueryMessage="";return message;}
function hasNodeCount(count,_node,_i,nodes){return count===nodes.length;}
function isChar(char){return!!char&&R_CHAR.test(char);}
function isDocument(object){return object?.nodeType===Node.DOCUMENT_NODE;}
function isElement(object){return object?.nodeType===Node.ELEMENT_NODE;}
function isNodeHaving(selector,node){return!!_queryAll(selector,{root:node}).length;}
function isNodeHidden(node){return!isNodeVisible(node);}
function isNodeInteractive(node){return(getStyle(node).pointerEvents!=="none"&&!node.closest?.("[inert]")&&!getParentFrame(node)?.inert);}
function isNodeNotMatching(selector,node){return!matches(node,selector);}
function isNodeSelected(node){return!!node.selected;}
function isOnlyNode(_node,_i,nodes){return nodes.length===1;}
function isQueryableNode(node){return QUERYABLE_NODE_TYPES.includes(node.nodeType);}
function isRootElement(el){return el&&R_ROOT_ELEMENT.test(el.nodeName||"");}
function isShadowRoot(el){return el.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&!!el.host;}
function isWindow(object){return object?.window===object&&object.constructor.name==="Window";}
function isWhiteSpace(char){return!!char&&R_HORIZONTAL_WHITESPACE.test(char);}
function makePseudoClassMatcher(getContent,exact){return function makePartialMatcher(content){const regex=parseRegExp(content);if(isInstanceOf(regex,RegExp)){return function stringMatches(node){return regex.test(getContent(node));};}else{const lowerContent=content.toLowerCase();if(exact){return function stringEquals(node){return getContent(node).toLowerCase()===lowerContent;};}else{return function stringContains(node){return getContent(node).toLowerCase().includes(lowerContent);};}}};}
function matchFilter(filter,nodes,index){if(typeof filter==="number"){if(filter<0){return filter+nodes.length===index;}else{return filter===index;}}
const node=nodes[index];if(typeof filter==="function"){return filter(node,index,nodes);}else{return!!node.matches?.(String(filter));}}
function nodeFlatMap(nodes,flatMapFn){const result=[];for(const node of nodes){const nodeList=flatMapFn(node);if(isNode(nodeList)){result.push(nodeList);}else if(isIterable(nodeList)){result.push(...nodeList);}}
return result;}
function parseNumberTuple(value,propsA,propsB){let result=[];if(value&&typeof value==="object"){if(isIterable(value)){[result[0],result[1]]=[...value];}else{for(const prop of propsA){result[0]??=value[prop];}
for(const prop of propsB){result[1]??=value[prop];}}}else{result=[value,value];}
return result.map($parseFloat);}
function parseRawArgs(args){return args[0]?.raw?[$raw(...args)]:args;}
function parseSelector(selector){function addToSelector(selector){registerChar=false;const index=currentPart.length-1;if(typeof currentPart[index]==="string"){currentPart[index]+=selector;}else{currentPart.push(selector);}}
const firstPart=[""];const firstGroup=[firstPart];const groups=[firstGroup];const parens=[0,0];let currentGroup=groups.at(-1);let currentPart=currentGroup.at(-1);let currentPseudo=null;let currentQuote=null;let registerChar=true;for(let i=0;i<selector.length;i++){const char=selector[i];registerChar=true;switch(char){case",":{if(!currentQuote&&!currentPseudo){groups.push([[""]]);currentGroup=groups.at(-1);currentPart=currentGroup.at(-1);registerChar=false;}
break;}
case" ":case"\t":case"\n":case"\r":case"\f":case"\v":{if(!currentQuote&&!currentPseudo){if(currentPart[0]||currentPart.length>1){currentGroup.push([""]);currentPart=currentGroup.at(-1);}
registerChar=false;}
break;}
case`'`:case`"`:{if(char===currentQuote){currentQuote=null;}else if(!currentQuote){currentQuote=char;}
break;}
case">":case"+":case"~":{if(!currentQuote&&!currentPseudo){while(isWhiteSpace(selector[i+1])){i++;}
addToSelector(char);}
break;}
case":":{if(!currentQuote&&!currentPseudo){let pseudo="";while(isChar(selector[i+1])){pseudo+=selector[++i];}
if(customPseudoClasses.has(pseudo)){if(selector[i+1]==="("){parens[0]++;i++;registerChar=false;}
currentPseudo=[pseudo,""];}else{addToSelector(char+pseudo);}}
break;}
case"(":{if(!currentQuote){parens[0]++;}
break;}
case")":{if(!currentQuote){parens[1]++;}
break;}}
if(currentPseudo){if(parens[0]===parens[1]){const[pseudo,content]=currentPseudo;if(pseudo==="iframe"&&!currentPart[0].startsWith("iframe")){currentPart[0]=`iframe${currentPart[0]}`;}
const filter=getQueryFilter(pseudo,getStringContent(content));selectorFilterDescriptors.set(filter,[pseudo,content]);currentPart.push(filter);currentPseudo=null;}else if(registerChar){currentPseudo[1]+=selector[i];}}else if(registerChar){addToSelector(selector[i]);}}
return groups;}
function parseXml(xmlString,type){const wrapperTag=type==="html"?"body":"templates";const doc=parser.parseFromString(`<${wrapperTag}>${xmlString}</${wrapperTag}>`,`text/${type}`);if(doc.getElementsByTagName("parsererror").length){const trimmed=xmlString.length>80?xmlString.slice(0,80)+"…":xmlString;throw new HootDomError(`error while parsing ${trimmed}: ${getNodeText(
                doc.getElementsByTagName("parsererror")[0]
            )}`);}
return doc.getElementsByTagName(wrapperTag)[0].childNodes;}
function pixelValueToNumber(val){return $parseFloat(val.endsWith("px")?val.slice(0,-2):val);}
function plural(word,count){return count===1?word:`${word}s`;}
function queryWithCustomSelector(nodes,selector){const selectorGroups=parseSelector(selector);const foundNodes=[];for(const selectorParts of selectorGroups){let groupNodes=nodes;for(const selectorPart of selectorParts){let baseSelector=selectorPart[0];let nodeGetter;switch(baseSelector[0]){case"+":{nodeGetter=NEXT_SIBLING;break;}
case">":{nodeGetter=DIRECT_CHILDREN;break;}
case"~":{nodeGetter=NEXT_SIBLINGS;break;}}
if(nodeGetter){baseSelector=baseSelector.slice(1);}
nodeGetter||=DESCENDANTS;const currentGroupNodes=nodeFlatMap(groupNodes,(node)=>nodeGetter(node,baseSelector));groupNodes=applyFilters(selectorPart.slice(1),currentGroupNodes);}
foundNodes.push(...groupNodes);}
return filterUniqueNodes(foundNodes);}
function registerQueryMessage(filteredNodes,expectedCount){lastQueryMessage="";const filteredCount=filteredNodes.length;const invalidCount=$isInteger(expectedCount)&&filteredCount!==expectedCount;if(shouldRegisterQueryMessage||invalidCount){const globalModifierInfo=[...globalFilterDescriptors.values()];lastQueryMessage+=`found ${filteredCount} ${plural("element", filteredCount)}`;if(invalidCount){lastQueryMessage+=` instead of ${expectedCount}`;}
const rootModifierInfo=globalModifierInfo.shift();const[,rootContent,initialCount=0]=rootModifierInfo;if(typeof rootContent==="string"){lastQueryMessage+=`: ${initialCount} matching ${JSON.stringify(rootContent)}`;if(selectorFilterDescriptors.size){const selectorModifierInfo=[...selectorFilterDescriptors.values()];lastQueryMessage+=` (${getFiltersDescription(selectorModifierInfo).join(" > ")})`;}}else if(filteredCount!==initialCount){lastQueryMessage+=`: ${initialCount} ${plural("element", initialCount)}`;}
if(initialCount){lastQueryMessage+=getFiltersDescription(globalModifierInfo).map((part)=>`, including ${part}`).join("");}}else{lastQueryMessage="";}
if(queryAllLevel<=1){globalFilterDescriptors.clear();selectorFilterDescriptors.clear();}
return invalidCount?lastQueryMessage:"";}
function _guardedQueryAll(target,options){try{return _queryAll(target,options);}catch(error){queryAllLevel=0;shouldRegisterQueryMessage=false;globalFilterDescriptors.clear();selectorFilterDescriptors.clear();throw error;}}
function _queryAll(target,options){queryAllLevel++;const{count,root,...modifiers}=options||{};if(count!==null&&count!==undefined&&(!$isInteger(count)||count<=0)){throw new HootDomError(`invalid 'count' option: should be a positive integer`);}
let nodes=[];let selector;if(typeof target==="string"){if(target){nodes=root?_queryAll(root):[getDefaultRoot()];}
selector=target.trim();}else if(isIterable(target)&&!isNode(target)){nodes=filterUniqueNodes(target);}else if(target){nodes=filterUniqueNodes([target]);}
globalFilterDescriptors.set("root",["",target]);if(selector&&nodes.length){if(rCustomPseudoClass.test(selector)){nodes=queryWithCustomSelector(nodes,selector);}else{nodes=filterUniqueNodes(nodeFlatMap(nodes,(node)=>DESCENDANTS(node,selector)));}}
globalFilterDescriptors.get("root").push(nodes.length);if(modifiers.visible&&modifiers.displayed){throw new HootDomError(`cannot use more than one visibility modifier ('visible' implies 'displayed')`);}
const modifierFilters=[];for(const[modifier,content]of $entries(modifiers)){if(content===false||!customPseudoClasses.has(modifier)){continue;}
const filter=getQueryFilter(modifier,content);modifierFilters.push(filter);globalFilterDescriptors.set(filter,[modifier,content]);}
const filteredNodes=applyFilters(modifierFilters,nodes);const message=registerQueryMessage(filteredNodes,count);if(message){throw new HootDomError(message);}
queryAllLevel--;return filteredNodes;}
function _queryOne(target,options){return _guardedQueryAll(target,{...options,count:1})[0];}
function _waitForFirst(target,options,isLast){shouldRegisterQueryMessage=isLast;const result=_guardedQueryAll(target,options)[0];shouldRegisterQueryMessage=false;return result;}
function _waitForNone(target,options,isLast){shouldRegisterQueryMessage=isLast;const result=_guardedQueryAll(target,options).length===0;shouldRegisterQueryMessage=false;return result;}
class HootDomError extends Error{name="HootDomError";}
const R_CHAR=/[\w-]/;const R_HORIZONTAL_WHITESPACE=/[\r\t\f \u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/g;const R_LINEBREAK=/\s*\n+\s*/g;const R_QUOTE_CONTENT=/^\s*(['"])?([^]*?)\1\s*$/;const R_ROOT_ELEMENT=/^(HTML|HEAD|BODY)$/;const R_SCROLLABLE_OVERFLOW=/\bauto\b|\bscroll\b/;const MODIFIER_SUFFIX_LABELS={contains:(content)=>`with text "${content}"`,eq:(content)=>`at index ${content}`,has:(content)=>`containing selector "${content}"`,not:(content)=>`not matching "${content}"`,value:(content)=>`with value "${content}"`,viewPort:()=>"in viewport",};const QUERYABLE_NODE_TYPES=[Node.ELEMENT_NODE,Node.DOCUMENT_NODE,Node.DOCUMENT_FRAGMENT_NODE];const parser=new DOMParser();function DIRECT_CHILDREN(node,selector){const children=[];for(const childNode of node.childNodes){if(childNode.matches?.(selector)){children.push(childNode);}}
return children;}
function DESCENDANTS(node,selector){return node.querySelectorAll?.(selector||"*");}
function NEXT_SIBLING(node,selector){const sibling=node.nextElementSibling;return sibling?.matches?.(selector)&&sibling;}
function NEXT_SIBLINGS(node,selector){const siblings=[];while((node=node.nextElementSibling)){if(node.matches?.(selector)){siblings.push(node);}}
return siblings;}
const globalFilterDescriptors=new Map();const selectorFilterDescriptors=new Map();const observers=new Map();const currentDimensions={width:innerWidth,height:innerHeight,};let getDefaultRoot=()=>document;let lastQueryMessage="";let shouldRegisterQueryMessage=false;let queryAllLevel=0;const customPseudoClasses=new Map();customPseudoClasses.set("contains",makePseudoClassMatcher(getInlineNodeText,false)).set("count",(strCount)=>{const count=$parseInt(strCount);if(!$isInteger(count)||count<=0){throw new HootDomError(`expected count to be a positive integer (got "${strCount}")`);}
return hasNodeCount.bind(null,count);}).set("displayed",()=>isNodeDisplayed).set("empty",()=>isEmpty).set("eq",(strIndex)=>{const index=$parseInt(strIndex);if(!$isInteger(index)){throw new HootDomError(`expected index to be an integer (got "${strIndex}")`);}
return index;}).set("first",()=>0).set("focusable",()=>isNodeFocusable).set("has",(selector)=>isNodeHaving.bind(null,selector)).set("hidden",()=>isNodeHidden).set("iframe",()=>getNodeIframe).set("interactive",()=>isNodeInteractive).set("last",()=>-1).set("not",(selector)=>isNodeNotMatching.bind(null,selector)).set("only",()=>isOnlyNode).set("scrollable",(axis)=>isNodeScrollable.bind(null,axis)).set("selected",()=>isNodeSelected).set("shadow",()=>getNodeShadowRoot).set("text",makePseudoClassMatcher(getInlineNodeText,true)).set("value",makePseudoClassMatcher(getRawValue,false)).set("viewPort",()=>isNodeInViewPort).set("visible",()=>isNodeVisible);const rCustomPseudoClass=compilePseudoClassRegex();__exports.cleanupDOM=cleanupDOM;function cleanupDOM(){currentDimensions.width=innerWidth;currentDimensions.height=innerHeight;const remainingObservers=observers.size;if(remainingObservers){for(const{observer}of observers.values()){observer.disconnect();}
observers.clear();}}
__exports.defineRootNode=defineRootNode;function defineRootNode(node){if(typeof node==="function"){getDefaultRoot=node;}else if(node){getDefaultRoot=()=>node;}else{getDefaultRoot=()=>document;}}
__exports.getCurrentDimensions=getCurrentDimensions;function getCurrentDimensions(){return currentDimensions;}
__exports.getDocument=getDocument;function getDocument(node){if(!node){return document;}
return isDocument(node)?node:node.ownerDocument||document;}
__exports.getNodeAttribute=getNodeAttribute;function getNodeAttribute(node,attribute){return node.getAttribute?.(attribute)??null;}
__exports.getNodeValue=getNodeValue;function getNodeValue(node,options){if(options?.raw){return getRawValue(node);}
switch(node.type){case"checkbox":case"radio":return node.checked;case"file":return[...node.files];case"number":case"range":return node.valueAsNumber;case"date":case"datetime-local":case"month":case"time":case"week":return node.valueAsDate.toISOString();default:return node.value||"";}}
__exports.getNodeRect=getNodeRect;function getNodeRect(node,options){if(!isElement(node)){return new DOMRect();}
const rect=node.getBoundingClientRect();const parentFrame=getParentFrame(node);if(parentFrame){const parentRect=getNodeRect(parentFrame);rect.x-=parentRect.x;rect.y-=parentRect.y;}
if(!options?.trimPadding){return rect;}
const style=getStyle(node);const{x,y,width,height}=rect;const[pl,pr,pt,pb]=["left","right","top","bottom"].map((side)=>pixelValueToNumber(style.getPropertyValue(`padding-${side}`)));return new DOMRect(x+pl,y+pt,width-(pl+pr),height-(pt+pb));}
__exports.getNodeText=getNodeText;function getNodeText(node,options){let content;if(typeof node.innerText==="string"){content=node.innerText;}else{content=node.textContent;}
if(!options?.raw){content=content.replace(R_HORIZONTAL_WHITESPACE," ").trim();}
if(options?.inline){content=content.replace(R_LINEBREAK," ");}
return content;}
__exports.getInteractiveNode=getInteractiveNode;function getInteractiveNode(node){let currentEl=ensureElement(node);if(!currentEl){return null;}
while(currentEl&&!isNodeInteractive(currentEl)){currentEl=currentEl.parentElement;}
return currentEl;}
__exports.getStyle=getStyle;function getStyle(node){return isElement(node)?getComputedStyle(node):null;}
__exports.getWindow=getWindow;function getWindow(node){if(!node){return window;}
return isWindow(node)?node:getDocument(node).defaultView;}
__exports.isCheckable=isCheckable;function isCheckable(node){switch(getTag(node)){case"input":return node.type==="checkbox"||node.type==="radio";case"label":return isCheckable(node.control);default:return false;}}
__exports.isEmpty=isEmpty;function isEmpty(value){if(!value){return true;}
if(typeof value==="object"){if(isNode(value)){return isEmpty(getNodeContent(value));}
if(!isIterable(value)){value=$keys(value);}
return[...value].length===0;}
return false;}
__exports.isEventTarget=isEventTarget;function isEventTarget(object){return object&&typeof object.addEventListener==="function";}
__exports.isNode=isNode;function isNode(object){return object&&typeof object.nodeType==="number"&&typeof object.nodeName==="string";}
__exports.isNodeCssVisible=isNodeCssVisible;function isNodeCssVisible(node){const element=ensureElement(node);if(element===getDefaultRoot()||isRootElement(element)){return true;}
const style=getStyle(element);if(style?.visibility==="hidden"||style?.opacity==="0"){return false;}
const parent=element.parentNode;return!parent||isNodeCssVisible(isShadowRoot(parent)?parent.host:parent);}
__exports.isNodeDisplayed=isNodeDisplayed;function isNodeDisplayed(node){const element=ensureElement(node);if(!isInDOM(element)){return false;}
if(isRootElement(element)||element.offsetParent||element.closest("svg")){return true;}
return!isFirefox()&&getStyle(element)?.position==="fixed";}
__exports.isNodeFocusable=isNodeFocusable;function isNodeFocusable(node,options){return(isNodeDisplayed(node)&&node.matches?.(FOCUSABLE_SELECTOR)&&(!options?.tabbable||node.tabIndex>=0));}
__exports.isNodeInViewPort=isNodeInViewPort;function isNodeInViewPort(node){const element=ensureElement(node);const{x,y}=getNodeRect(element);return y>0&&y<currentDimensions.height&&x>0&&x<currentDimensions.width;}
__exports.isNodeScrollable=isNodeScrollable;function isNodeScrollable(axis,node){if(!isElement(node)){return false;}
const isScrollableX=node.clientWidth<node.scrollWidth;const isScrollableY=node.clientHeight<node.scrollHeight;switch(axis){case"both":{if(!isScrollableX||!isScrollableY){return false;}
break;}
case"x":{if(!isScrollableX){return false;}
break;}
case"y":{if(!isScrollableY){return false;}
break;}
default:{if(!isScrollableX&&!isScrollableY){return false;}}}
const overflow=getStyle(node).getPropertyValue("overflow");if(R_SCROLLABLE_OVERFLOW.test(overflow)){return true;}
return false;}
__exports.isNodeVisible=isNodeVisible;function isNodeVisible(node){const element=ensureElement(node);if(!isNodeDisplayed(element)||!isNodeCssVisible(element)){return false;}
let visible=false;const{width,height}=getNodeRect(element);visible=width>0&&height>0;if(!visible&&getStyle(element)?.display==="contents"){for(const child of element.childNodes){if(isNodeVisible(child)){return true;}}}
return visible;}
__exports.parseDimensions=parseDimensions;function parseDimensions(dimensions){return parseNumberTuple(dimensions,["width","w"],["height","h"]);}
__exports.parsePosition=parsePosition;function parsePosition(position){return parseNumberTuple(position,["x","left","clientX","pageX","screenX"],["y","top","clientY","pageY","screenY"]);}
__exports.setDimensions=setDimensions;function setDimensions(width,height){const defaultRoot=getDefaultRoot();if(!$isNaN(width)){currentDimensions.width=width;defaultRoot.style?.setProperty("width",`${width}px`,"important");}
if(!$isNaN(height)){currentDimensions.height=height;defaultRoot.style?.setProperty("height",`${height}px`,"important");}}
__exports.toSelector=toSelector;function toSelector(node,options){const parts={tag:node.nodeName.toLowerCase(),};if(node.id){parts.id=`#${node.id}`;}
if(node.classList?.length){parts.class=`.${[...node.classList].join(".")}`;}
return options?.object?parts:$values(parts).join("");}
const FOCUSABLE_SELECTOR=__exports.FOCUSABLE_SELECTOR=["a[href]","area[href]","button:enabled","details > summary:first-of-type","iframe","input:enabled","select:enabled","textarea:enabled","[tabindex]","[contenteditable=true]",].join(",");__exports.formatXml=formatXml;function formatXml(value,options){const nodes=parseXml(value,options?.type||"xml");const layers=extractLayers(nodes,0,options?.keepInlineTextNodes??false);return generateStringFromLayers(layers,options?.tabSize??4);}
__exports.getActiveElement=getActiveElement;function getActiveElement(node){const doc=getDocument(node);const view=doc.defaultView;const{activeElement}=doc;const{contentDocument,shadowRoot}=activeElement;if(contentDocument&&contentDocument.activeElement!==contentDocument.body){if(contentDocument.activeElement===contentDocument.body){return contentDocument.activeElement;}else{return getActiveElement(contentDocument);}}
if(shadowRoot){return shadowRoot.activeElement;}
if(activeElement===doc.body&&view!==view.parent){return getActiveElement(view.parent.document);}
return activeElement;}
__exports.getFocusableElements=getFocusableElements;function getFocusableElements(options){const parent=_queryOne(options?.root||getDefaultRoot());if(typeof parent.querySelectorAll!=="function"){return[];}
const byTabIndex={};for(const element of parent.querySelectorAll(FOCUSABLE_SELECTOR)){const{tabIndex}=element;if((options?.tabbable&&tabIndex<0)||!isNodeDisplayed(element)){continue;}
if(!byTabIndex[tabIndex]){byTabIndex[tabIndex]=[];}
byTabIndex[tabIndex].push(element);}
const withTabIndexZero=byTabIndex[0]||[];delete byTabIndex[0];return[...$values(byTabIndex).flat(),...withTabIndexZero];}
__exports.getNextFocusableElement=getNextFocusableElement;function getNextFocusableElement(options){const parent=_queryOne(options?.root||getDefaultRoot());const focusableEls=getFocusableElements({...options,parent});const index=focusableEls.indexOf(getActiveElement(parent));return focusableEls[index+1]||null;}
__exports.getParentFrame=getParentFrame;function getParentFrame(node){const doc=getDocument(node);if(!doc){return null;}
const view=doc.defaultView;if(view!==view.parent){for(const iframe of view.parent.document.getElementsByTagName("iframe")){if(iframe.contentWindow===view){return iframe;}}}
return null;}
__exports.getPreviousFocusableElement=getPreviousFocusableElement;function getPreviousFocusableElement(options){const parent=_queryOne(options?.root||getDefaultRoot());const focusableEls=getFocusableElements({...options,parent});const index=focusableEls.indexOf(getActiveElement(parent));return index<0?focusableEls.at(-1):focusableEls[index-1]||null;}
__exports.isDisplayed=isDisplayed;function isDisplayed(target){return _guardedQueryAll(target,{displayed:true}).length>0;}
__exports.isEditable=isEditable;function isEditable(node){return(isElement(node)&&!node.matches?.(":disabled")&&["input","textarea"].includes(getTag(node)));}
__exports.isFocusable=isFocusable;function isFocusable(target){return _guardedQueryAll(target,{focusable:true}).length>0;}
__exports.isInDOM=isInDOM;function isInDOM(target){return ensureElement(target)?.isConnected;}
__exports.isInViewPort=isInViewPort;function isInViewPort(target){return _guardedQueryAll(target,{viewPort:true}).length>0;}
__exports.isScrollable=isScrollable;function isScrollable(target,axis){return _guardedQueryAll(target,{scrollable:axis}).length>0;}
__exports.isVisible=isVisible;function isVisible(target){return _guardedQueryAll(target,{visible:true}).length>0;}
__exports.matches=matches;function matches(target,selector){return elementsMatch(_guardedQueryAll(target),selector);}
__exports.queryAll=queryAll;function queryAll(target,options){[target,options]=parseRawArgs(arguments);return _guardedQueryAll(target,options);}
__exports.queryAllAttributes=queryAllAttributes;function queryAllAttributes(target,attribute,options){return _guardedQueryAll(target,options).map((node)=>getNodeAttribute(node,attribute));}
__exports.queryAllProperties=queryAllProperties;function queryAllProperties(target,property,options){return _guardedQueryAll(target,options).map((node)=>node[property]);}
__exports.queryAllRects=queryAllRects;function queryAllRects(target,options){[target,options]=parseRawArgs(arguments);return _guardedQueryAll(target,options).map(getNodeRect);}
__exports.queryAllTexts=queryAllTexts;function queryAllTexts(target,options){[target,options]=parseRawArgs(arguments);return _guardedQueryAll(target,options).map((node)=>getNodeText(node,options));}
__exports.queryAllValues=queryAllValues;function queryAllValues(target,options){[target,options]=parseRawArgs(arguments);return _guardedQueryAll(target,options).map((node)=>getNodeValue(node,options));}
__exports.queryAny=queryAny;function queryAny(target,options){[target,options]=parseRawArgs(arguments);return _queryOne(target,ensureCount(options));}
__exports.queryAttribute=queryAttribute;function queryAttribute(target,attribute,options){return getNodeAttribute(_queryOne(target,options),attribute);}
__exports.queryFirst=queryFirst;function queryFirst(target,options){[target,options]=parseRawArgs(arguments);return _guardedQueryAll(target,options)[0]||null;}
__exports.queryOne=queryOne;function queryOne(target,options){[target,options]=parseRawArgs(arguments);if($isInteger(options?.count)){throw new HootDomError(`cannot call \`queryOne\` with 'count'=${options.count}: did you mean to use \`queryAll\`?`);}
return _queryOne(target,options);}
__exports.queryRect=queryRect;function queryRect(target,options){[target,options]=parseRawArgs(arguments);return getNodeRect(_queryOne(target,options),options);}
__exports.queryText=queryText;function queryText(target,options){[target,options]=parseRawArgs(arguments);return getNodeText(_queryOne(target,options),options);}
__exports.queryValue=queryValue;function queryValue(target,options){[target,options]=parseRawArgs(arguments);return getNodeValue(_queryOne(target,options),options);}
__exports.waitFor=waitFor;function waitFor(target,options){[target,options]=parseRawArgs(arguments);return waitUntil(_waitForFirst.bind(null,target,options),{message:getWaitForMessage,...options,});}
__exports.waitForNone=waitForNone;function waitForNone(target,options){[target,options]=parseRawArgs(arguments);return waitUntil(_waitForNone.bind(null,target,options),{message:getWaitForNoneMessage,...options,});}
return __exports;});;

/* /web/static/lib/hoot-dom/helpers/events.js */
odoo.define('@web/../lib/hoot-dom/helpers/events',['@web/../lib/hoot-dom/hoot_dom_utils','@web/../lib/hoot-dom/helpers/dom'],function(require){'use strict';let __exports={};const{getColorHex,getTag,isFirefox,isInstanceOf,isIterable}=require("@web/../lib/hoot-dom/hoot_dom_utils");const{getActiveElement,getDocument,getInteractiveNode,getNextFocusableElement,getNodeRect,getNodeValue,getParentFrame,getPreviousFocusableElement,getStyle,getWindow,isCheckable,isEditable,isEventTarget,isNode,isNodeFocusable,parseDimensions,parsePosition,queryAll,queryAny,setDimensions,toSelector,}=require("@web/../lib/hoot-dom/helpers/dom");const{AnimationEvent,ClipboardEvent,CompositionEvent,console:{dir:$dir,groupCollapsed:$groupCollapsed,groupEnd:$groupEnd,log:$log},DataTransfer,document,DragEvent,Error,ErrorEvent,Event,File,FocusEvent,HashChangeEvent,HTMLElement,KeyboardEvent,Math:{ceil:$ceil,max:$max,min:$min},MouseEvent,Number:{isInteger:$isInteger,isNaN:$isNaN,parseFloat:$parseFloat},Object:{assign:$assign,create:$create,defineProperties:$defineProperties,values:$values,},PointerEvent,PromiseRejectionEvent,String,SubmitEvent,Touch,TouchEvent,TypeError,WheelEvent,}=globalThis;const $createRange=document.createRange.bind(document);const $toString=Object.prototype.toString;const $blur=HTMLElement.prototype.blur;HTMLElement.prototype.blur=function mockBlur(){if(runTime.changeTarget&&runTime.changeTarget===this){triggerChange();}
return $blur.call(this,...arguments);};const $focus=HTMLElement.prototype.focus;HTMLElement.prototype.focus=function mockFocus(){if(runTime.changeTarget&&runTime.changeTarget!==this){triggerChange();}
return $focus.call(this,...arguments);};function cancelTrustedEvent(ev){if(ev.isTrusted&&runTime.eventsToIgnore.includes(ev.type)){runTime.eventsToIgnore.splice(runTime.eventsToIgnore.indexOf(ev.type),1);ev.stopPropagation();ev.stopImmediatePropagation();ev.preventDefault();}}
async function changeSelection(target,start,end){if(!isNil(start)&&!isNil(target.selectionStart)){target.selectionStart=start;}
if(!isNil(end)&&!isNil(target.selectionEnd)){target.selectionEnd=end;}}
function constrainScrollX(target,x){let{offsetWidth,scrollWidth}=target;const document=getDocument(target);if(target===document||target===document.documentElement){const iframe=getParentFrame(target);if(iframe){({offsetWidth}=iframe);}}
const maxScrollLeft=scrollWidth-offsetWidth;const{direction}=getStyle(target);const[min,max]=direction==="rtl"?[-maxScrollLeft,0]:[0,maxScrollLeft];return $min($max(x,min),max);}
function constrainScrollY(target,y){let{offsetHeight,scrollHeight}=target;const document=getDocument(target);if(target===document||target===document.documentElement){const iframe=getParentFrame(target);if(iframe){({offsetHeight}=iframe);}}
return $min($max(y,0),scrollHeight-offsetHeight);}
function createDataTransfer(options){const dataTransfer=isInstanceOf(options?.dataTransfer,DataTransfer)?options.dataTransfer:new DataTransfer();for(const file of options?.files||[]){if(!isInstanceOf(file,File)){throw new TypeError(`'DataTransfer.files' list only accepts 'File' objects`);}
dataTransfer.items.add(file);}
for(const[data,type]of options?.items||[]){dataTransfer.items.add(data,type);}
$defineProperties(dataTransfer,{dropEffect:{value:options?.dropEffect||"none",writable:true},effectAllowed:{value:options?.effectAllowed||"all",writable:true},});return dataTransfer;}
function deleteSelection(target){const{selectionStart,selectionEnd,value}=target;return value.slice(0,selectionStart)+value.slice(selectionEnd);}
async function dispatchAndIgnore({target,events,additionalEvents=[],callback,options}){for(const eventType of[...events,...additionalEvents]){runTime.eventsToIgnore.push(eventType);}
callback?.();for(const eventType of events){await _dispatch(target,eventType,options);}}
async function dispatchPointerEvent(target,eventType,eventInit,{mouse,touch}){const pointerEvent=await _dispatch(target,eventType,eventInit);let prevented=isPrevented(pointerEvent);if(hasTouch()){if(touch&&runTime.pointerDownTarget){const[touchEventType,touchEventInit]=touch;await _dispatch(runTime.pointerDownTarget,touchEventType,touchEventInit||eventInit);}}else{if(mouse&&!prevented){const[mouseEventType,mouseEventInit]=mouse;const mouseEvent=await _dispatch(target,mouseEventType,mouseEventInit||eventInit);prevented=isPrevented(mouseEvent);}}
return prevented;}
async function dispatchRelatedEvents(events,eventType,eventInit){for(const event of events){if(!event.target||isPrevented(event)){break;}
await _dispatch(event.target,eventType,eventInit);}}
function ensureArray(value,mapFn){if(Array.isArray(value)){return mapFn?value.map(mapFn):value;}
if(isIterable(value)){return Array.from(value,mapFn);}
return[mapFn?mapFn(value):value];}
function getCurrentEvents(){const eventType=currentEventTypes.at(-1);if(!eventType){return[];}
currentEvents[eventType]||=[];return currentEvents[eventType];}
function getDefaultRunTimeValue(){return{changeTarget:null,changeTargetListeners:[],clipboardData:null,dataTransfer:null,initialValue:null,isComposing:false,key:null,canStartDrag:false,isDragging:false,lastDragOverCancelled:false,clickCount:0,pointerDownTarget:null,pointerDownTimeout:0,pointerTarget:null,position:{},previousPointerDownTarget:null,touchStartPosition:{},fileInput:null,buttons:0,modifierKeys:{},eventsToIgnore:[],};}
function getDifferentParents(el1,el2){if(!el1&&!el2){return[];}else if(!el1&&el2){[el1,el2]=[el2,el1];}
const parents=[el2||el1];while(parents[0].parentElement){const parent=parents[0].parentElement;if(el2&&parent.contains(el1)){break;}
parents.unshift(parent);}
return parents;}
function getEventConstructor(eventType){switch(eventType){case"dblclick":case"mousedown":case"mouseup":case"mousemove":case"mouseover":case"mouseout":return[MouseEvent,mapMouseEvent,BUBBLES|CANCELABLE|VIEW];case"mouseenter":case"mouseleave":return[MouseEvent,mapMouseEvent,VIEW];case"auxclick":case"click":case"contextmenu":case"pointerdown":case"pointerup":case"pointermove":case"pointerover":case"pointerout":return[PointerEvent,mapPointerEvent,BUBBLES|CANCELABLE|VIEW];case"pointerenter":case"pointerleave":case"pointercancel":return[PointerEvent,mapPointerEvent,VIEW];case"blur":case"focus":return[FocusEvent,mapEvent];case"focusin":case"focusout":return[FocusEvent,mapEvent,BUBBLES];case"cut":case"copy":case"paste":return[ClipboardEvent,mapEvent,BUBBLES];case"keydown":case"keyup":return[KeyboardEvent,mapKeyboardEvent,BUBBLES|CANCELABLE|VIEW];case"drag":case"dragend":case"dragenter":case"dragstart":case"dragleave":case"dragover":case"drop":return[DragEvent,mapEvent,BUBBLES|CANCELABLE];case"beforeinput":return[InputEvent,mapInputEvent,BUBBLES|CANCELABLE|VIEW];case"input":return[InputEvent,mapInputEvent,BUBBLES|VIEW];case"compositionstart":case"compositionend":return[CompositionEvent,mapEvent,BUBBLES];case"select":case"selectionchange":return[Event,mapEvent,BUBBLES];case"touchstart":case"touchend":case"touchmove":return[TouchEvent,mapTouchEvent,BUBBLES|CANCELABLE|VIEW];case"touchcancel":return[TouchEvent,mapTouchEvent,BUBBLES|VIEW];case"resize":return[Event,mapEvent];case"submit":return[SubmitEvent,mapEvent,BUBBLES|CANCELABLE];case"wheel":return[WheelEvent,mapWheelEvent,BUBBLES|VIEW];case"animationcancel":case"animationend":case"animationiteration":case"animationstart":{return[AnimationEvent,mapEvent,BUBBLES|CANCELABLE];}
case"error":return[ErrorEvent,mapEvent];case"unhandledrejection":return[PromiseRejectionEvent,mapEvent,CANCELABLE];case"beforeunload":return[Event,mapEvent,CANCELABLE];case"unload":return[Event,mapEvent];case"hashchange":return[HashChangeEvent,mapEvent];default:return[Event,mapEvent,BUBBLES];}}
function getFirstCommonParent(a,b){if(!a||!b||a.ownerDocument!==b.ownerDocument){return null;}
const range=document.createRange();range.setStart(a,0);range.setEnd(b,0);if(range.collapsed){range.setStart(b,0);range.setEnd(a,0);}
return range.commonAncestorContainer;}
function getPointerTarget(element,options,originalTarget){if(!element||options?.interactive===false){return element;}
const interactiveElement=getInteractiveNode(element);if(!interactiveElement&&originalTarget){queryAny(originalTarget,{...options,interactive:true});}
return interactiveElement;}
function getPosition(element,options){const{position,relative}=options||{};const isString=typeof position==="string";const[posX,posY]=parsePosition(position);if(!isString&&!relative&&!$isNaN(posX)&&!$isNaN(posY)){return toEventPosition(posX,posY,position);}
const{x,y,width,height}=getNodeRect(element);let clientX=x;let clientY=y;if(isString){const positions=position.split("-");if(positions.includes("left")){clientX-=1;}else if(positions.includes("right")){clientX+=$ceil(width)+1;}else{clientX+=width/2;}
if(positions.includes("top")){clientY-=1;}else if(positions.includes("bottom")){clientY+=$ceil(height)+1;}else{clientY+=height/2;}}else{if($isNaN(posX)){clientX+=width/2;}else{if(relative){clientX+=posX||0;}else{clientX=posX||0;}}
if($isNaN(posY)){clientY+=height/2;}else{if(relative){clientY+=posY||0;}else{clientY=posY||0;}}}
return toEventPosition(clientX,clientY,position);}
function getStringSelection(target){return($isInteger(target.selectionStart)&&$isInteger(target.selectionEnd)&&[target.selectionStart,target.selectionEnd].join(","));}
function hasTagName(node,...tagNames){return tagNames.includes(getTag(node));}
function hasTouch(){return(globalThis.ontouchstart!==undefined||globalThis.matchMedia("(pointer:coarse)").matches);}
function isDifferentPosition(position){if(!runTime.position||!position){return runTime.position!==position;}
for(const key in position){if(runTime.position[key]!==position[key]){return true;}}
return false;}
function isDictionary(object){return $toString.call(object)==="[object Object]";}
function isNil(value){return value===null||value===undefined;}
function isPrevented(event){return event&&event.defaultPrevented;}
function parseKeyStrokes(keyStrokes,options){return ensureArray(keyStrokes,(key)=>{const lower=key.toLowerCase();return{...options,key:lower.length===1?key:KEY_ALIASES[lower]||key,};});}
function redirectSubmit(ev){if(isPrevented(ev)){return;}
ev.preventDefault();const form=ev.target;globalThis.fetch(form.action,{method:form.method,body:new FormData(form,ev.submitter),});}
function registerButton(eventInit,toggle){let value=0;switch(eventInit.button){case btn.LEFT:{value=1;break;}
case btn.MIDDLE:{value=4;break;}
case btn.RIGHT:{value=2;break;}
case btn.BACK:{value=8;break;}
case btn.FORWARD:{value=16;break;}}
runTime.buttons=$max(runTime.buttons+(toggle?value:-value),0);}
function registerFileInput({target}){const actualTarget=target.shadowRoot?target.shadowRoot.activeElement:target;if(getTag(actualTarget)==="input"&&actualTarget.type==="file"){runTime.fileInput=actualTarget;}else{runTime.fileInput=null;}}
async function registerForChange(target,confirmAction){confirmAction&&=confirmAction.toLowerCase();if(confirmAction==="auto"){confirmAction=getTag(target)==="input"?"enter":"blur";}
const parentDocument=getDocument(target);const parentView=parentDocument.defaultView;if(confirmAction==="enter"&&getTag(target)!=="input"){throw new HootInteractionError(`"enter" confirm action is only supported on <input/> elements`);}
runTime.changeTarget=target;runTime.changeTargetListeners.push(on(parentView,"focusout",triggerChange),on(parentView,"change",removeChangeTargetListeners));switch(confirmAction){case"blur":{await _hover(parentDocument.body,{position:{x:0,y:0}},{originalTarget:target});await _click();break;}
case"enter":{await _press(target,{key:"Enter"});break;}
case"tab":{await _press(target,{key:"Tab"});break;}}}
function registerSpecialKey(eventInit,toggle){switch(eventInit.key){case"Alt":{runTime.modifierKeys.altKey=toggle;break;}
case"Control":{runTime.modifierKeys.ctrlKey=toggle;break;}
case"Meta":{runTime.modifierKeys.metaKey=toggle;break;}
case"Shift":{runTime.modifierKeys.shiftKey=toggle;break;}}}
function removeChangeTargetListeners(){for(const listener of runTime.changeTargetListeners){listener();}
runTime.changeTarget=null;runTime.changeTargetListeners=[];}
function resolve(resolver){return typeof resolver==="function"?resolver():resolver;}
function setPointerDownTarget(target,options){if(runTime.pointerDownTarget){runTime.previousPointerDownTarget=runTime.pointerDownTarget;}
runTime.pointerDownTarget=getPointerTarget(target,options);runTime.canStartDrag=false;}
function setupEvents(type,options){currentEventTypes.push(type);$assign(currentEventInit,options?.eventInit);return function finalizeEvents(){for(const eventType in currentEventInit){delete currentEventInit[eventType];}
const events=new EventList(getCurrentEvents());const currentType=currentEventTypes.pop();delete currentEvents[currentType];if(!allowLogs){return events;}
const groupName=[`%c[${type}]%c dispatched`,`color: ${getColorHex("purple")}`,"",events.length,`events`,];$groupCollapsed(...groupName);for(const event of events){const colors=[getColorHex("text-report-html-tag")];const typeList=[event.type];if(event.key){typeList.push(event.key);}else if(event.button){typeList.push(event.button);}
[...Array(typeList.length)].forEach(()=>colors.push(getColorHex("text-report-string")));const typeString=typeList.map((t)=>`%c"${t}"%c`).join(", ");let message=`%c${event.constructor.name}%c<${typeString}>`;if(event.__bubbleCount){message+=` (${event.__bubbleCount})`;}
const target=event.__originalTarget||event.target;if(isNode(target)){const targetParts=toSelector(target,{object:true});colors.push(getColorHex("text-report-html-tag"));if(targetParts.id){colors.push(getColorHex("text-report-html-id"));}
if(targetParts.class){colors.push(getColorHex("text-report-html-class"));}
const targetString=$values(targetParts).map((part)=>`%c${part}%c`).join("");message+=` @${targetString}`;}
const messageColors=colors.flatMap((color)=>[`color: ${color}; font-weight: normal`,"",]);$groupCollapsed(message,...messageColors);$dir(event);$log(target);$groupEnd();}
$groupEnd();return events;};}
function toEventPosition(clientX,clientY,position){clientX||=0;clientY||=0;return{clientX,clientY,pageX:position?.pageX??clientX,pageY:position?.pageY??clientY,screenX:position?.screenX??clientX,screenY:position?.screenY??clientY,};}
async function triggerChange(){const target=runTime.changeTarget;const hasValueChanged=runTime.initialValue!==target.value;runTime.initialValue=null;removeChangeTargetListeners();if(target&&hasValueChanged){return _dispatch(target,"change");}}
async function triggerClick(target,pointerInit){if(target.disabled){return;}
const eventType=(pointerInit.button??0)===btn.LEFT?"click":"auxclick";const clickEvent=await _dispatch(target,eventType,pointerInit);if(isPrevented(clickEvent)){return;}
if(isFirefox()){switch(getTag(target)){case"label":{target=target.control;if(target){await triggerClick(target,pointerInit);}
break;}
case"option":{const parent=target.parentElement;if(parent&&getTag(parent)==="select"){await _dispatch(parent,"change");}
break;}}}}
async function triggerDrag(target,eventInit){await _dispatch(target,"drag",eventInit);const dragOverEvent=await _dispatch(target,"dragover",eventInit);return isPrevented(dragOverEvent);}
async function triggerFocus(target){const previous=getActiveElement(target);if(previous===target){return;}
if(previous!==target.ownerDocument.body){if(runTime.changeTarget){await triggerChange();}
await dispatchAndIgnore({target:previous,events:["blur","focusout"],callback:$blur.bind(previous),options:{relatedTarget:target},});}
if(isNodeFocusable(target)){const previousSelection=getStringSelection(target);await dispatchAndIgnore({target,events:["focus","focusin"],additionalEvents:["select"],callback:$focus.bind(target),options:{relatedTarget:previous},});if(previousSelection&&previousSelection===getStringSelection(target)){changeSelection(target,target.value.length,target.value.length);}}}
async function _clear(targetResolver,options){await _press(targetResolver,{ctrlKey:true,key:"a"});await _press(targetResolver,{key:"Backspace"},{fullClear:true});await registerForChange(resolve(targetResolver),options?.confirm);}
async function _click(options){await _pointerDown(options);await _pointerUp(options);}
async function _dispatch(target,type,eventInit){eventInit={...eventInit,...currentEventInit[type]};for(const key in eventInit){if(key in DEPRECATED_EVENT_PROPERTIES){throw new HootInteractionError(`cannot dispatch "${type}" event: property "${key}" is deprecated, use "${DEPRECATED_EVENT_PROPERTIES[key]}" instead`);}}
const[Constructor,processParams,flags]=getEventConstructor(type);const params=processParams({composed:true,...eventInit,target,type,});if(flags&BUBBLES){params.bubbles=true;}
if(flags&CANCELABLE){params.cancelable=true;}
if(flags&VIEW){params.view||=getWindow(target);}
const event=new Constructor(type,params);target.dispatchEvent(event);await Promise.resolve();getCurrentEvents().push(event);return event;}
async function _fill(targetResolver,value,options){const initialTarget=resolve(targetResolver);if(getTag(initialTarget)==="input"){switch(initialTarget.type){case"color":case"time":{initialTarget.value=String(value);await _dispatch(initialTarget,"input");await _dispatch(initialTarget,"change");return;}
case"file":{const files=ensureArray(value);if(files.length>1&&!initialTarget.multiple){throw new HootInteractionError(`input[type="file"] does not support multiple files`);}
initialTarget.files=createDataTransfer({files}).files;await _dispatch(initialTarget,"change");return;}
case"range":{const numberValue=$parseFloat(value);if($isNaN(numberValue)){throw new TypeError(`input[type="range"] only accept 'number' values`);}
initialTarget.value=String(numberValue);await _dispatch(initialTarget,"input");await _dispatch(initialTarget,"change");return;}}}
if(options?.instantly){globalThis.navigator.clipboard.writeText(value).catch();await _press(targetResolver,{ctrlKey:true,key:"v"});}else{if(options?.composition){runTime.isComposing=true;await _dispatch(initialTarget,"compositionstart");}
for(const char of String(value)){const key=char.toLowerCase();await _press(targetResolver,{key,shiftKey:key!==char});}
if(options?.composition){runTime.isComposing=false;await _dispatch(initialTarget,"compositionend");}}
await registerForChange(resolve(targetResolver),options?.confirm);}
async function _hover(target,options,hoverOptions){const pointerTarget=getPointerTarget(target,options,hoverOptions.originalTarget);const position=target&&getPosition(target,options);const previousPT=runTime.pointerTarget;const previousPosition=runTime.position;const isDifferentTarget=previousPT!==pointerTarget;if(hoverOptions?.implicit&&!isDifferentTarget&&!isDifferentPosition(position)){return;}
if(runTime.canStartDrag){const dragStartEvent=await _dispatch(previousPT,"dragstart",{dataTransfer:runTime.dataTransfer,});runTime.isDragging=!isPrevented(dragStartEvent);runTime.canStartDrag=false;}
runTime.pointerTarget=pointerTarget;runTime.position=position;if(isDifferentTarget&&previousPT&&(!pointerTarget||!previousPT.contains(pointerTarget))){const leaveEventInit={...previousPosition,relatedTarget:pointerTarget,button:options?.button||0,};if(runTime.isDragging){const leaveEventInitWithDT={...leaveEventInit,dataTransfer:runTime.dataTransfer};runTime.lastDragOverCancelled=await triggerDrag(previousPT,leaveEventInitWithDT);await _dispatch(previousPT,"dragleave",leaveEventInitWithDT);}else{await dispatchPointerEvent(previousPT,"pointermove",leaveEventInit,{mouse:["mousemove"],touch:["touchmove"],});await dispatchPointerEvent(previousPT,"pointerout",leaveEventInit,{mouse:["mouseout"],});const leaveEvents=await Promise.all(getDifferentParents(pointerTarget,previousPT).map((element)=>_dispatch(element,"pointerleave",leaveEventInit)));if(!hasTouch()){await dispatchRelatedEvents(leaveEvents,"mouseleave",leaveEventInit);}}}
if(!pointerTarget){return;}
const enterEventInit={...runTime.position,relatedTarget:previousPT,button:options?.button||0,};if(runTime.isDragging){const enterEventInitWithDT={...enterEventInit,dataTransfer:runTime.dataTransfer};runTime.lastDragOverCancelled=false;if(isDifferentTarget){const dragEnterEvent=await _dispatch(pointerTarget,"dragenter",enterEventInitWithDT);runTime.lastDragOverCancelled=isPrevented(dragEnterEvent);}
runTime.lastDragOverCancelled||=await triggerDrag(pointerTarget,enterEventInitWithDT);}else{if(isDifferentTarget){await dispatchPointerEvent(pointerTarget,"pointerover",enterEventInit,{mouse:["mouseover"],});const enterEvents=await Promise.all(getDifferentParents(previousPT,pointerTarget).map((element)=>_dispatch(element,"pointerenter",enterEventInit)));if(!hasTouch()){await dispatchRelatedEvents(enterEvents,"mouseenter",enterEventInit);}}
await dispatchPointerEvent(pointerTarget,"pointermove",enterEventInit,{mouse:["mousemove"],touch:["touchmove"],});}}
async function _keyDown(targetResolver,eventInit,options){eventInit={...eventInit,...currentEventInit.keydown};registerSpecialKey(eventInit,true);const keyDownTarget=resolve(targetResolver);const repeat=typeof eventInit.repeat==="boolean"?eventInit.repeat:runTime.key===eventInit.key;runTime.key=eventInit.key;const keyDownEvent=await _dispatch(keyDownTarget,"keydown",{...eventInit,repeat,});if(isPrevented(keyDownEvent)){return;}
function insertValue(toInsert,type){const{selectionStart,selectionEnd,value}=inputTarget;inputData=toInsert;inputType=type;if(isNil(selectionStart)&&isNil(selectionEnd)){nextValue||=inputTarget.value;nextValue+=toInsert;}else{nextValue=value.slice(0,selectionStart)+toInsert+value.slice(selectionEnd);if(selectionStart===selectionEnd){nextSelectionStart=nextSelectionEnd=selectionStart+1;}}}
const{ctrlKey,key,shiftKey}=keyDownEvent;const inputTarget=resolve(targetResolver);let inputData=null;let inputType=null;let nextSelectionEnd=null;let nextSelectionStart=null;let nextValue=null;let triggerSelect=false;if(runTime.initialValue===null||keyDownTarget!==inputTarget){runTime.initialValue=inputTarget.value;}
if(isEditable(inputTarget)){switch(key){case"ArrowDown":case"ArrowLeft":case"ArrowUp":case"ArrowRight":{const{selectionStart,selectionEnd,value}=inputTarget;if(isNil(selectionStart)||isNil(selectionEnd)){break;}
const start=key==="ArrowLeft"||key==="ArrowUp";let selectionTarget;if(ctrlKey){selectionTarget=start?0:value.length;}else{selectionTarget=start?selectionStart-1:selectionEnd+1;}
nextSelectionStart=nextSelectionEnd=$max($min(selectionTarget,value.length),0);triggerSelect=shiftKey;break;}
case"Backspace":{const{selectionStart,selectionEnd,value}=inputTarget;if(options?.fullClear){nextValue="";}else if(isNil(selectionStart)||isNil(selectionEnd)){nextValue=value.slice(0,-1);}else if(selectionStart===selectionEnd){nextValue=value.slice(0,selectionStart-1)+value.slice(selectionEnd);}else{nextValue=deleteSelection(inputTarget);}
inputType="deleteContentBackward";break;}
case"Delete":{const{selectionStart,selectionEnd,value}=inputTarget;if(isNil(selectionStart)||isNil(selectionEnd)){nextValue=value.slice(1);}else if(selectionStart===selectionEnd){nextValue=value.slice(0,selectionStart)+value.slice(selectionEnd+1);}else{nextValue=deleteSelection(inputTarget);}
inputType="deleteContentForward";break;}
default:{if(key.length===1&&!ctrlKey){insertValue(shiftKey?key.toUpperCase():key.toLowerCase(),runTime.isComposing?"insertCompositionText":"insertText");}}}}
switch(key){case"a":{if(ctrlKey){if(isEditable(inputTarget)){nextSelectionStart=0;nextSelectionEnd=inputTarget.value.length;triggerSelect=true;}else{const selection=globalThis.getSelection();const range=$createRange();range.selectNodeContents(inputTarget);selection.removeAllRanges();selection.addRange(range);}}
break;}
case"c":{if(ctrlKey){const text=globalThis.getSelection().toString();globalThis.navigator.clipboard.writeText(text).catch();runTime.clipboardData=createDataTransfer(eventInit);await _dispatch(inputTarget,"copy",{clipboardData:runTime.clipboardData});}
break;}
case"Enter":{if(runTime.changeTarget){await triggerChange();}
if(inputTarget.tagName==="TEXTAREA"&&isEditable(inputTarget)){insertValue("\n","insertLineBreak");}
const tag=getTag(inputTarget);const parentForm=inputTarget.closest("form");if(parentForm&&inputTarget.type!=="button"){await _dispatch(parentForm,"submit");}else if(!keyDownEvent.repeat&&(tag==="a"||tag==="button"||(tag==="input"&&inputTarget.type==="button"))){await _dispatch(inputTarget,"click",{button:btn.LEFT});}
break;}
case"Escape":{runTime.dataTransfer=null;runTime.isDragging=false;break;}
case"Tab":{const next=shiftKey?getPreviousFocusableElement({tabbable:true}):getNextFocusableElement({tabbable:true});if(next){await triggerFocus(next);}
break;}
case"v":{if(ctrlKey&&isEditable(inputTarget)){try{nextValue=await globalThis.navigator.clipboard.readText();}catch{}
inputType="insertFromPaste";await _dispatch(inputTarget,"paste",{clipboardData:runTime.clipboardData||createDataTransfer(eventInit),});runTime.clipboardData=null;}
break;}
case"x":{if(ctrlKey&&isEditable(inputTarget)){const text=globalThis.getSelection().toString();globalThis.navigator.clipboard.writeText(text).catch();nextValue=deleteSelection(inputTarget);inputType="deleteByCut";runTime.clipboardData=createDataTransfer(eventInit);await _dispatch(inputTarget,"cut",{clipboardData:runTime.clipboardData});}
break;}}
if(nextValue!==null){inputTarget.value=nextValue;const inputEventInit={data:inputData,inputType,};const beforeInputEvent=await _dispatch(inputTarget,"beforeinput",inputEventInit);if(!isPrevented(beforeInputEvent)){await _dispatch(inputTarget,"input",inputEventInit);}}
changeSelection(inputTarget,nextSelectionStart,nextSelectionEnd);if(triggerSelect){await dispatchAndIgnore({target:inputTarget,events:["select"],});}}
async function _keyUp(targetResolver,eventInit){eventInit={...eventInit,...currentEventInit.keyup};await _dispatch(resolve(targetResolver),"keyup",eventInit);runTime.key=null;registerSpecialKey(eventInit,false);const finalTarget=resolve(targetResolver);if(eventInit.key===" "&&getTag(finalTarget)==="input"&&finalTarget.type==="checkbox"){await triggerClick(finalTarget,{button:btn.LEFT});}}
async function _pointerDown(options){setPointerDownTarget(runTime.pointerTarget,options);if(options?.dataTransfer||options?.files||options?.items){runTime.dataTransfer=createDataTransfer(options);}
const pointerDownTarget=runTime.pointerDownTarget;const eventInit={...runTime.position,...currentEventInit.pointerdown,button:options?.button||btn.LEFT,};registerButton(eventInit,true);if(pointerDownTarget!==runTime.previousPointerDownTarget){runTime.clickCount=0;}
runTime.touchStartPosition={...runTime.position};runTime.touchStartTimeOffset=globalThis.Date.now();const prevented=await dispatchPointerEvent(pointerDownTarget,"pointerdown",eventInit,{mouse:!pointerDownTarget.disabled&&["mousedown",{...eventInit,detail:runTime.clickCount+1},],touch:["touchstart"],});if(prevented){return;}
await triggerFocus(pointerDownTarget);if(eventInit.button===btn.LEFT&&!hasTouch()&&(pointerDownTarget.draggable||runTime.dataTransfer)){runTime.canStartDrag=true;}else if(eventInit.button===btn.RIGHT){await _dispatch(pointerDownTarget,"contextmenu",eventInit);}}
async function _pointerUp(options){const target=runTime.pointerTarget;const isLongTap=globalThis.Date.now()-runTime.touchStartTimeOffset>LONG_TAP_DELAY;const pointerDownTarget=runTime.pointerDownTarget;const pointerUpTarget=getPointerTarget(target,options);const eventInit={...runTime.position,...currentEventInit.pointerup,button:options?.button||btn.LEFT,};registerButton(eventInit,false);if(runTime.isDragging){const eventInitWithDT={...eventInit,dataTransfer:runTime.dataTransfer};runTime.dataTransfer=null;runTime.isDragging=false;if(runTime.lastDragOverCancelled){await _dispatch(pointerUpTarget,"drop",eventInitWithDT);}
await _dispatch(pointerUpTarget,"dragend",eventInitWithDT);return;}
const mouseEventInit={...eventInit,detail:runTime.clickCount+1,};await dispatchPointerEvent(pointerUpTarget,"pointerup",eventInit,{mouse:!pointerUpTarget.disabled&&["mouseup",mouseEventInit],touch:["touchend"],});const touchStartPosition=runTime.touchStartPosition;runTime.touchStartPosition={};if(hasTouch()&&(isDifferentPosition(touchStartPosition)||isLongTap)){return;}
let clickTarget;if(hasTouch()){clickTarget=pointerDownTarget===pointerUpTarget&&pointerUpTarget;}else{clickTarget=getFirstCommonParent(pointerUpTarget,pointerDownTarget);}
if(clickTarget){await triggerClick(clickTarget,mouseEventInit);if(mouseEventInit.button===btn.LEFT){runTime.clickCount++;if(!hasTouch()&&runTime.clickCount%2===0){await _dispatch(clickTarget,"dblclick",mouseEventInit);}}}
setPointerDownTarget(null,options);if(runTime.pointerDownTimeout){globalThis.clearTimeout(runTime.pointerDownTimeout);}
runTime.pointerDownTimeout=globalThis.setTimeout(()=>{runTime.clickCount=0;runTime.pointerDownTimeout=0;},DOUBLE_CLICK_DELAY);}
async function _press(targetResolver,eventInit,options){await _keyDown(targetResolver,eventInit,options);await _keyUp(targetResolver,eventInit);}
async function _select(target,value){const values=ensureArray(value,String);let found=false;for(const option of target.options){option.selected=values.includes(option.value);found||=option.selected;}
if(!value){target.selectedIndex=-1;}else if(!found){throw new HootInteractionError(`error when calling \`select()\`: no option found with value "${values.join(", ")}"`);}
await _dispatch(target,"change");}
class HootInteractionError extends Error{name="HootInteractionError";}
const btn={LEFT:0,MIDDLE:1,RIGHT:2,BACK:3,FORWARD:4,};const CAPTURE={capture:true};const DEPRECATED_EVENT_PROPERTIES={keyCode:"key",which:"key",};const DEPRECATED_EVENTS={keypress:"keydown",mousewheel:"wheel",};const DOUBLE_CLICK_DELAY=500;const GLOBAL_TRUSTED_EVENTS_CANCELERS=[["blur",cancelTrustedEvent,CAPTURE],["focus",cancelTrustedEvent,CAPTURE],["focusin",cancelTrustedEvent,CAPTURE],["focusout",cancelTrustedEvent,CAPTURE],["scroll",cancelTrustedEvent,CAPTURE],["scrollend",cancelTrustedEvent,CAPTURE],["select",cancelTrustedEvent,CAPTURE],];const GLOBAL_FILE_INPUT_REGISTERERS=[["click",registerFileInput,CAPTURE],["focus",registerFileInput,CAPTURE],];const GLOBAL_SUBMIT_FORWARDERS=[["submit",redirectSubmit]];const KEY_ALIASES={alt:"Alt",arrowdown:"ArrowDown",arrowleft:"ArrowLeft",arrowright:"ArrowRight",arrowup:"ArrowUp",backspace:"Backspace",control:"Control",delete:"Delete",enter:"Enter",escape:"Escape",meta:"Meta",shift:"Shift",tab:"Tab",caps:"Shift",cmd:"Meta",command:"Meta",ctrl:"Control",del:"Delete",down:"ArrowDown",esc:"Escape",left:"ArrowLeft",right:"ArrowRight",space:" ",up:"ArrowUp",win:"Meta",};const LONG_TAP_DELAY=500;const currentEvents=$create(null);const currentEventInit=$create(null);const currentEventTypes=[];let allowLogs=false;const runTime=getDefaultRunTimeValue();const BUBBLES=0b1;const CANCELABLE=0b10;const VIEW=0b100;function mapEvent(eventInit){return eventInit;}
function mapMouseEvent(eventInit){return{button:-1,buttons:runTime.buttons,clientX:eventInit.clientX??eventInit.pageX??eventInit.screenX??0,clientY:eventInit.clientY??eventInit.pageY??eventInit.screenY??0,...runTime.modifierKeys,...eventInit,};}
function mapPointerEvent(eventInit){return{...mapMouseEvent(eventInit),button:btn.LEFT,isPrimary:eventInit?.btn?eventInit.btn===btn.LEFT:true,pointerId:1,pointerType:hasTouch()?"touch":"mouse",...eventInit,};}
function mapWheelEvent(eventInit){return{...mapMouseEvent(eventInit),button:btn.LEFT,...eventInit,};}
function mapTouchEvent(eventInit){const touches=eventInit.targetTouches||eventInit.touches||[new Touch({identifier:0,...eventInit})];return{...eventInit,changedTouches:eventInit.changedTouches||touches,target:eventInit.target,targetTouches:eventInit.targetTouches||touches,touches:eventInit.touches||(eventInit.type==="touchend"?[]:touches),};}
function mapInputEvent(eventInit){return{data:null,isComposing:!!runTime.isComposing,...eventInit,};}
function mapKeyboardEvent(eventInit){return{isComposing:!!runTime.isComposing,...runTime.modifierKeys,...eventInit,};}
__exports.check=check;async function check(target,options){const finalizeEvents=setupEvents("check",options);const element=queryAny(await target,options);if(!isCheckable(element)){throw new HootInteractionError(`cannot call \`check()\`: target should be a checkbox or radio input`);}
const checkTarget=getTag(element)==="label"?element.control:element;if(!checkTarget.checked){await _hover(element,options,{implicit:true,originalTarget:target});await _click(options);if(!checkTarget.checked){throw new HootInteractionError(`error when calling \`check()\`: target is not checked after interaction`);}}
return finalizeEvents();}
__exports.cleanupEvents=cleanupEvents;function cleanupEvents(){if(runTime.pointerDownTimeout){globalThis.clearTimeout(runTime.pointerDownTimeout);}
removeChangeTargetListeners();$assign(runTime,getDefaultRunTimeValue());}
__exports.clear=clear;async function clear(options){const finalizeEvents=setupEvents("clear",options);const activeElement=getActiveElement();if(!hasTagName(activeElement,"select")&&!isEditable(activeElement)){throw new HootInteractionError(`cannot call \`clear()\`: target should be editable or a <select> element`);}
if(isEditable(activeElement)){await _clear(getActiveElement,options);}else{await _select(activeElement,"");}
return finalizeEvents();}
__exports.click=click;async function click(target,options){const finalizeEvents=setupEvents("click",options);const element=queryAny(await target,options);await _hover(element,options,{implicit:true,originalTarget:target});await _click(options);return finalizeEvents();}
__exports.dblclick=dblclick;async function dblclick(target,options){const finalizeEvents=setupEvents("dblclick",options);const element=queryAny(await target,options);options={...options,button:btn.LEFT};await _hover(element,options,{implicit:true,originalTarget:target});await _click(options);await _click(options);return finalizeEvents();}
__exports.dispatch=dispatch;async function dispatch(target,type,eventInit){const finalizeEvents=setupEvents("dispatch");if(!isEventTarget(target)){throw new HootInteractionError(`cannot dispatch "${type}" event: expected target to be an 'EventTarget', got: ${target}`);}
if(type in DEPRECATED_EVENTS){throw new HootInteractionError(`cannot dispatch "${type}" event: this event type is deprecated, use "${DEPRECATED_EVENTS[type]}" instead`);}
if(type!==type.toLowerCase()){throw new HootInteractionError(`cannot dispatch "${type}" event: this event type is either non-standard or deprecated`);}
await _dispatch(target,type,eventInit);return finalizeEvents();}
__exports.drag=drag;async function drag(target,options){function expectIsDragging(fn,endDrag){return{async[fn.name](...args){if(dragEndReason){throw new HootInteractionError(`cannot execute drag helper \`${fn.name}\`: drag sequence has been ended by \`${dragEndReason}\``);}
const result=await fn(...args);if(endDrag){dragEndReason=fn.name;}
return result;},}[fn.name];}
const cancel=expectIsDragging(async function cancel(options){const finalizeEvents=setupEvents("drag & drop: cancel",options);const bodyElement=getDocument(runTime.pointerTarget).body;runTime.buttons=0;await _press(bodyElement,{key:"Escape"});dragEvents.push(...finalizeEvents());return dragEvents;},true);const drop=expectIsDragging(async function drop(to,options){if(to){await moveTo(to,options);if(isDictionary(to)){options=to;}}
const finalizeEvents=setupEvents("drag & drop: drop",options);await _pointerUp(options);dragEvents.push(...finalizeEvents());return dragEvents;},true);const moveTo=expectIsDragging(async function moveTo(to,options){if(isDictionary(to)){[to,options]=[null,to];}
const finalizeEvents=setupEvents("drag & drop: move",options);const nextElement=to?queryAny(await to,options):runTime.pointerTarget;await _hover(nextElement,options,{originalTarget:to});dragEvents.push(...finalizeEvents());return dragHelpers;},false);const finalizeEvents=setupEvents("drag & drop: start",options);const dragHelpers={cancel,drop,moveTo};const dragStartTarget=queryAny(await target,options);let dragEndReason=null;await _hover(dragStartTarget,options,{implicit:true,originalTarget:target});await _pointerDown(options);const dragEvents=finalizeEvents();return dragHelpers;}
__exports.edit=edit;async function edit(value,options){const finalizeEvents=setupEvents("edit",options);const activeElement=getActiveElement();if(!isEditable(activeElement)){throw new HootInteractionError(`cannot call \`edit()\`: target should be editable`);}
if(getNodeValue(activeElement)){await _clear(getActiveElement);}
await _fill(getActiveElement,value,options);return finalizeEvents();}
__exports.enableEventLogs=enableEventLogs;function enableEventLogs(toggle){allowLogs=toggle??true;}
__exports.fill=fill;async function fill(value,options){const finalizeEvents=setupEvents("fill",options);if(!isEditable(getActiveElement())){throw new HootInteractionError(`cannot call \`fill()\`: target should be editable`);}
await _fill(getActiveElement,value,options);return finalizeEvents();}
__exports.hover=hover;async function hover(target,options){const finalizeEvents=setupEvents("hover",options);const element=queryAny(await target,options);await _hover(element,options,{originalTarget:target});return finalizeEvents();}
__exports.keyDown=keyDown;async function keyDown(keyStrokes,options){const finalizeEvents=setupEvents("keyDown",options);const eventInits=parseKeyStrokes(keyStrokes,options);for(const eventInit of eventInits){await _keyDown(getActiveElement,eventInit);}
return finalizeEvents();}
__exports.keyUp=keyUp;async function keyUp(keyStrokes,options){const finalizeEvents=setupEvents("keyUp",options);const eventInits=parseKeyStrokes(keyStrokes,options);for(const eventInit of eventInits){await _keyUp(getActiveElement,eventInit);}
return finalizeEvents();}
__exports.leave=leave;async function leave(options){const finalizeEvents=setupEvents("leave",options);await _hover(null,options,{originalTarget:window});return finalizeEvents();}
__exports.middleClick=middleClick;async function middleClick(target,options){const finalizeEvents=setupEvents("middleClick",options);const element=queryAny(await target,options);options={...options,button:btn.MIDDLE};await _hover(element,options,{implicit:true,originalTarget:target});await _click(options);return finalizeEvents();}
__exports.on=on;function on(target,type,listener,options){const targets=isEventTarget(target)?[target]:queryAll(target);if(!targets.length){throw new HootInteractionError(`expected at least 1 event target, got none`);}
for(const eventTarget of targets){eventTarget.addEventListener(type,listener,options);}
return function off(){for(const eventTarget of targets){eventTarget.removeEventListener(type,listener,options);}};}
__exports.pointerDown=pointerDown;async function pointerDown(target,options){const finalizeEvents=setupEvents("pointerDown",options);const element=queryAny(await target,options);await _hover(element,options,{implicit:true,originalTarget:target});await _pointerDown(options);return finalizeEvents();}
__exports.pointerUp=pointerUp;async function pointerUp(target,options){const finalizeEvents=setupEvents("pointerUp",options);const element=queryAny(await target,options);await _hover(element,options,{implicit:true,originalTarget:target});await _pointerUp(options);return finalizeEvents();}
__exports.press=press;async function press(keyStrokes,options){const finalizeEvents=setupEvents("press",options);const eventInits=parseKeyStrokes(keyStrokes,options);for(const eventInit of eventInits){await _keyDown(getActiveElement,eventInit);}
for(const eventInit of eventInits.reverse()){await _keyUp(getActiveElement,eventInit);}
return finalizeEvents();}
__exports.resize=resize;async function resize(dimensions,options){const finalizeEvents=setupEvents("resize",options);const[width,height]=parseDimensions(dimensions);setDimensions(width,height);await _dispatch(getWindow(),"resize");return finalizeEvents();}
__exports.rightClick=rightClick;async function rightClick(target,options){const finalizeEvents=setupEvents("rightClick",options);const element=queryAny(await target,options);options={...options,button:btn.RIGHT};await _hover(element,options,{implicit:true,originalTarget:target});await _click(options);return finalizeEvents();}
__exports.scroll=scroll;async function scroll(target,position,options){const finalizeEvents=setupEvents("scroll",options);let[x,y]=parsePosition(position);options={initiator:"wheel",scrollable:x&&y?"both":x?"x":y?"y":true,...options,};const{force,initiator,relative}=options;const scrollTopOptions={};const element=queryAny(await target,options);if(relative){x+=element.scrollLeft;y+=element.scrollTop;}
if(!$isNaN(x)){const targetX=force?x:constrainScrollX(element,x);if(targetX!==element.scrollLeft){scrollTopOptions.left=targetX;}}
if(!$isNaN(y)){const targetY=force?y:constrainScrollY(element,y);if(targetY!==element.scrollTop){scrollTopOptions.top=targetY;}}
const keys=[];if(initiator==="keyboard"){if(x<element.scrollLeft){keys.push("ArrowRight");}else if(x>element.scrollLeft){keys.push("ArrowLeft");}
if(y<element.scrollTop){keys.push("ArrowDown");}else if(y>element.scrollTop){keys.push("ArrowUp");}
await Promise.all(keys.map((key)=>_keyDown(key)));}else if(!hasTouch()&&initiator==="wheel"){const wheelEventInit={};if(!$isNaN(x)){wheelEventInit.deltaX=x-element.scrollLeft;}
if(!$isNaN(y)){wheelEventInit.deltaY=y-element.scrollTop;}
await _dispatch(element,"wheel",wheelEventInit);}
if(force||$values(scrollTopOptions).length){await dispatchAndIgnore({target:element,events:["scroll","scrollend"],callback:()=>element.scrollTo(scrollTopOptions),});}
if(initiator==="keyboard"){await Promise.all(keys.map((key)=>_keyUp(key)));}
return finalizeEvents();}
__exports.select=select;async function select(value,options){const finalizeEvents=setupEvents("select",options);const manualTarget=options?.target;const element=manualTarget?queryAny(await manualTarget):getActiveElement();if(!hasTagName(element,"select")){throw new HootInteractionError(`cannot call \`select()\`: target should be a <select> element`);}
if(manualTarget){await _hover(element,null,{implicit:true,originalTarget:manualTarget});await _pointerDown();}
await _select(element,value);if(manualTarget){await _pointerUp();}
return finalizeEvents();}
__exports.setInputFiles=setInputFiles;async function setInputFiles(files,options){if(!runTime.fileInput){throw new HootInteractionError(`cannot call \`setInputFiles()\`: no file input has been interacted with`);}
const finalizeEvents=setupEvents("setInputFiles",options);await _fill(runTime.fileInput,files,options);runTime.fileInput=null;return finalizeEvents();}
__exports.setInputRange=setInputRange;async function setInputRange(target,value,options){const finalizeEvents=setupEvents("setInputRange",options);const element=queryAny(await target,options);await _hover(element,options,{implicit:true,originalTarget:target});await _pointerDown(options);await _fill(element,value,options);await _pointerUp(options);return finalizeEvents();}
__exports.setupEventActions=setupEventActions;function setupEventActions(target,options){const eventHandlers=[];if(!options?.allowTrustedEvents){eventHandlers.push(...GLOBAL_TRUSTED_EVENTS_CANCELERS);}
if(!options?.noFileInputRegistration){eventHandlers.push(...GLOBAL_FILE_INPUT_REGISTERERS);}
if(!options?.allowSubmit){eventHandlers.push(...GLOBAL_SUBMIT_FORWARDERS);}
const view=getWindow(target);for(const[eventType,handler,options]of eventHandlers){view.addEventListener(eventType,handler,options);}
return function cleanupEventActions(){for(const[eventType,handler,options]of eventHandlers){view.removeEventListener(eventType,handler,options);}};}
__exports.uncheck=uncheck;async function uncheck(target,options){const finalizeEvents=setupEvents("uncheck",options);const element=queryAny(await target,options);if(!isCheckable(element)){throw new HootInteractionError(`cannot call \`uncheck()\`: target should be a checkbox or radio input`);}
const checkTarget=getTag(element)==="label"?element.control:element;if(checkTarget.checked){await _hover(element,options,{implicit:true,originalTarget:target});await _click(options);if(checkTarget.checked){throw new HootInteractionError(`error when calling \`uncheck()\`: target is still checked after interaction`);}}
return finalizeEvents();}
__exports.unload=unload;async function unload(options){const finalizeEvents=setupEvents("unload",options);await _dispatch(getWindow(),"beforeunload");return finalizeEvents();}
const EventList=__exports.EventList=class EventList extends Array{constructor(...args){super(...args.flat());}
get(predicate){return this.getAll(predicate)[0]||null;}
getAll(predicate){if(typeof predicate!=="function"){const type=predicate;predicate=function isSameType(ev){return ev.type===type;};}
return this.filter(predicate);}}
return __exports;});;

/* /web/static/lib/hoot-dom/helpers/time.js */
odoo.define('@web/../lib/hoot-dom/helpers/time',['@web/../lib/hoot-dom/hoot_dom_utils'],function(require){'use strict';let __exports={};const{isInstanceOf}=require("@web/../lib/hoot-dom/hoot_dom_utils");const{cancelAnimationFrame,clearInterval,clearTimeout,Error,Math:{ceil:$ceil,floor:$floor,max:$max,min:$min},Number,performance,Promise,requestAnimationFrame,setInterval,setTimeout,}=globalThis;const $performanceNow=performance.now.bind(performance);function animationToId(id){return ID_PREFIX.animation+String(id);}
function getNextTimerValues(){let timerValues=null;for(const[internalId,[callback,init,delay]]of timers.entries()){const timeout=init+delay;if(!timerValues||timeout<timerValues[0]){timerValues=[timeout,callback,internalId];}}
return timerValues;}
function idToAnimation(id){return Number(id.slice(ID_PREFIX.animation.length));}
function idToInterval(id){return Number(id.slice(ID_PREFIX.interval.length));}
function idToTimeout(id){return Number(id.slice(ID_PREFIX.timeout.length));}
function intervalToId(id){return ID_PREFIX.interval+String(id);}
function parseNat(value){return $max($floor(Number(value)),0)||0;}
function now(){return(frozen?0:$performanceNow())+timeOffset;}
function timeoutToId(id){return ID_PREFIX.timeout+String(id);}
class HootTimingError extends Error{name="HootTimingError";}
const ID_PREFIX={animation:"a_",interval:"i_",timeout:"t_",};const timers=new Map();let allowTimers=false;let frozen=false;let frameDelay=1000/60;let nextDummyId=1;let timeOffset=0;__exports.advanceFrame=advanceFrame;function advanceFrame(frameCount,options){return advanceTime(frameDelay*parseNat(frameCount),options);}
__exports.advanceTime=advanceTime;async function advanceTime(ms,options){ms=parseNat(ms);if(options?.blockTimers){allowTimers=false;}
const targetTime=now()+ms;let remaining=ms;let timerValues;while((timerValues=getNextTimerValues())&&timerValues[0]<=targetTime){const[timeout,handler,id]=timerValues;const diff=timeout-now();if(diff>0){timeOffset+=$min(remaining,diff);remaining=$max(remaining-diff,0);}
if(timers.has(id)){handler(timeout);}}
if(remaining>0){timeOffset+=remaining;}
if(options?.animationFrame??true){await animationFrame();}
allowTimers=true;return ms;}
__exports.animationFrame=animationFrame;function animationFrame(){return new Promise((resolve)=>requestAnimationFrame(()=>setTimeout(resolve)));}
__exports.cancelAllTimers=cancelAllTimers;function cancelAllTimers(){for(const id of timers.keys()){if(id.startsWith(ID_PREFIX.animation)){globalThis.cancelAnimationFrame(idToAnimation(id));}else if(id.startsWith(ID_PREFIX.interval)){globalThis.clearInterval(idToInterval(id));}else if(id.startsWith(ID_PREFIX.timeout)){globalThis.clearTimeout(idToTimeout(id));}}}
__exports.cleanupTime=cleanupTime;function cleanupTime(){allowTimers=false;frozen=false;cancelAllTimers();return delay();}
__exports.delay=delay;function delay(duration){return new Promise((resolve)=>setTimeout(resolve,duration));}
__exports.freezeTime=freezeTime;function freezeTime(){frozen=true;}
__exports.unfreezeTime=unfreezeTime;function unfreezeTime(){frozen=false;}
__exports.getTimeOffset=getTimeOffset;function getTimeOffset(){return timeOffset;}
__exports.isTimeFrozen=isTimeFrozen;function isTimeFrozen(){return frozen;}
__exports.microTick=microTick;function microTick(){return new Promise(queueMicrotask);}
__exports.mockedCancelAnimationFrame=mockedCancelAnimationFrame;function mockedCancelAnimationFrame(handle){if(!frozen){cancelAnimationFrame(handle);}
timers.delete(animationToId(handle));}
__exports.mockedClearInterval=mockedClearInterval;function mockedClearInterval(intervalId){if(!frozen){clearInterval(intervalId);}
timers.delete(intervalToId(intervalId));}
__exports.mockedClearTimeout=mockedClearTimeout;function mockedClearTimeout(timeoutId){if(!frozen){clearTimeout(timeoutId);}
timers.delete(timeoutToId(timeoutId));}
__exports.mockedRequestAnimationFrame=mockedRequestAnimationFrame;function mockedRequestAnimationFrame(callback){if(!allowTimers){return 0;}
function handler(){mockedCancelAnimationFrame(handle);return callback(now());}
const animationValues=[handler,now(),frameDelay];const handle=frozen?nextDummyId++:requestAnimationFrame(handler);const internalId=animationToId(handle);timers.set(internalId,animationValues);return handle;}
__exports.mockedSetInterval=mockedSetInterval;function mockedSetInterval(callback,ms,...args){if(!allowTimers){return 0;}
ms=parseNat(ms);function handler(){if(allowTimers){intervalValues[1]=$max(now(),intervalValues[1]+ms);}else{mockedClearInterval(intervalId);}
return callback(...args);}
const intervalValues=[handler,now(),ms];const intervalId=frozen?nextDummyId++:setInterval(handler,ms);const internalId=intervalToId(intervalId);timers.set(internalId,intervalValues);return intervalId;}
__exports.mockedSetTimeout=mockedSetTimeout;function mockedSetTimeout(callback,ms,...args){if(!allowTimers){return 0;}
ms=parseNat(ms);function handler(){mockedClearTimeout(timeoutId);return callback(...args);}
const timeoutValues=[handler,now(),ms];const timeoutId=frozen?nextDummyId++:setTimeout(handler,ms);const internalId=timeoutToId(timeoutId);timers.set(internalId,timeoutValues);return timeoutId;}
__exports.resetTimeOffset=resetTimeOffset;function resetTimeOffset(){timeOffset=0;}
__exports.runAllTimers=runAllTimers;function runAllTimers(options){if(!timers.size){return 0;}
const endts=$max(...[...timers.values()].map(([,init,delay])=>init+delay));return advanceTime($ceil(endts-now()),options);}
__exports.setFrameRate=setFrameRate;function setFrameRate(frameRate){frameRate=parseNat(frameRate);if(frameRate<1||frameRate>1000){throw new HootTimingError("frame rate must be an number between 1 and 1000");}
frameDelay=1000/frameRate;}
__exports.setupTime=setupTime;function setupTime(){allowTimers=true;}
__exports.tick=tick;function tick(){return delay();}
__exports.waitUntil=waitUntil;async function waitUntil(predicate,options){await Promise.resolve();const result=predicate(false);if(result){return result;}
const timeout=$floor(options?.timeout??200);const maxFrameCount=$ceil(timeout/frameDelay);let frameCount=0;let handle;return new Promise((resolve,reject)=>{function runCheck(){const isLast=++frameCount>=maxFrameCount;const result=predicate(isLast);if(result){resolve(result);}else if(!isLast){handle=requestAnimationFrame(runCheck);}else{let message=options?.message||`'waitUntil' timed out after %timeout% milliseconds`;if(typeof message==="function"){message=message();}
if(isInstanceOf(message,Error)){reject(message);}else{reject(new HootTimingError(message.replace("%timeout%",String(timeout))));}}}
handle=requestAnimationFrame(runCheck);}).finally(()=>{cancelAnimationFrame(handle);});}
const Deferred=__exports.Deferred=class Deferred extends Promise{_resolve;_reject;constructor(executor){let _resolve,_reject;super(function deferredResolver(resolve,reject){_resolve=resolve;_reject=reject;executor?.(_resolve,_reject);});this._resolve=_resolve;this._reject=_reject;}
async reject(reason){return this._reject(reason);}
async resolve(value){return this._resolve(value);}}
return __exports;});;

/* /web/static/lib/hoot-dom/hoot-dom.js */
odoo.define('@web/../lib/hoot-dom/hoot-dom',['@web/../lib/hoot-dom/helpers/dom','@web/../lib/hoot-dom/helpers/events','@web/../lib/hoot-dom/helpers/time','@web/../lib/hoot-dom/hoot_dom_utils'],function(require){'use strict';let __exports={};const dom=require("@web/../lib/hoot-dom/helpers/dom");const events=require("@web/../lib/hoot-dom/helpers/events");const time=require("@web/../lib/hoot-dom/helpers/time");const{interactor}=require("@web/../lib/hoot-dom/hoot_dom_utils");{const{formatXml,getActiveElement,getFocusableElements,getNextFocusableElement,getParentFrame,getPreviousFocusableElement,isDisplayed,isEditable,isFocusable,isInDOM,isInViewPort,isScrollable,isVisible,matches,queryAll,queryAllAttributes,queryAllProperties,queryAllRects,queryAllTexts,queryAllValues,queryAny,queryAttribute,queryFirst,queryOne,queryRect,queryText,queryValue,}=require("@web/../lib/hoot-dom/helpers/dom");Object.assign(__exports,{formatXml,getActiveElement,getFocusableElements,getNextFocusableElement,getParentFrame,getPreviousFocusableElement,isDisplayed,isEditable,isFocusable,isInDOM,isInViewPort,isScrollable,isVisible,matches,queryAll,queryAllAttributes,queryAllProperties,queryAllRects,queryAllTexts,queryAllValues,queryAny,queryAttribute,queryFirst,queryOne,queryRect,queryText,queryValue,})};{const{on}=require("@web/../lib/hoot-dom/helpers/events");Object.assign(__exports,{on})};{const{animationFrame,cancelAllTimers,Deferred,delay,freezeTime,unfreezeTime,microTick,setFrameRate,tick,waitUntil,}=require("@web/../lib/hoot-dom/helpers/time");Object.assign(__exports,{animationFrame,cancelAllTimers,Deferred,delay,freezeTime,unfreezeTime,microTick,setFrameRate,tick,waitUntil,})};const waitFor=__exports.waitFor=interactor("query",dom.waitFor);const waitForNone=__exports.waitForNone=interactor("query",dom.waitForNone);const check=__exports.check=interactor("interaction",events.check);const clear=__exports.clear=interactor("interaction",events.clear);const click=__exports.click=interactor("interaction",events.click);const dblclick=__exports.dblclick=interactor("interaction",events.dblclick);const drag=__exports.drag=interactor("interaction",events.drag);const edit=__exports.edit=interactor("interaction",events.edit);const fill=__exports.fill=interactor("interaction",events.fill);const hover=__exports.hover=interactor("interaction",events.hover);const keyDown=__exports.keyDown=interactor("interaction",events.keyDown);const keyUp=__exports.keyUp=interactor("interaction",events.keyUp);const leave=__exports.leave=interactor("interaction",events.leave);const manuallyDispatchProgrammaticEvent=__exports.manuallyDispatchProgrammaticEvent=interactor("interaction",events.dispatch);const middleClick=__exports.middleClick=interactor("interaction",events.middleClick);const pointerDown=__exports.pointerDown=interactor("interaction",events.pointerDown);const pointerUp=__exports.pointerUp=interactor("interaction",events.pointerUp);const press=__exports.press=interactor("interaction",events.press);const resize=__exports.resize=interactor("interaction",events.resize);const rightClick=__exports.rightClick=interactor("interaction",events.rightClick);const scroll=__exports.scroll=interactor("interaction",events.scroll);const select=__exports.select=interactor("interaction",events.select);const setInputFiles=__exports.setInputFiles=interactor("interaction",events.setInputFiles);const setInputRange=__exports.setInputRange=interactor("interaction",events.setInputRange);const uncheck=__exports.uncheck=interactor("interaction",events.uncheck);const unload=__exports.unload=interactor("interaction",events.unload);const advanceFrame=__exports.advanceFrame=interactor("time",time.advanceFrame);const advanceTime=__exports.advanceTime=interactor("time",time.advanceTime);const runAllTimers=__exports.runAllTimers=interactor("time",time.runAllTimers);{const{exposeHelpers}=require("@web/../lib/hoot-dom/hoot_dom_utils");Object.assign(__exports,{exposeHelpers})};return __exports;});odoo.define(`@odoo/hoot-dom`,['@web/../lib/hoot-dom/hoot-dom'],function(require){return require('@web/../lib/hoot-dom/hoot-dom');});;

/* /web/static/lib/hoot-dom/hoot_dom_utils.js */
odoo.define('@web/../lib/hoot-dom/hoot_dom_utils',[],function(require){'use strict';let __exports={};const{Array:{isArray:$isArray},matchMedia,navigator:{userAgent:$userAgent},Object:{assign:$assign,getPrototypeOf:$getPrototypeOf},RegExp,SyntaxError,}=globalThis;const $toString=Object.prototype.toString;function makeInteractorFn(type,fn,name,alias){return{[alias||name](...args){const result=fn(...args);if(isPromise(result)){for(let i=0;i<args.length;i++){if(isPromise(args[i])){args[i].then((result)=>(args[i]=result));}}
return result.then((promiseResult)=>dispatchInteraction(type,name,alias,args,promiseResult));}else{return dispatchInteraction(type,name,alias,args,result);}},}[alias||name];}
function polyfillIsError(value){return $toString.call(value)==="[object Error]";}
const GRAYS={100:"#f1f5f9",200:"#e2e8f0",300:"#cbd5e1",400:"#94a3b8",500:"#64748b",600:"#475569",700:"#334155",800:"#1e293b",900:"#0f172a",};const COLORS={default:{black:"#000000",white:"#ffffff","gray-100":GRAYS[100],"gray-200":GRAYS[200],"gray-300":GRAYS[300],"gray-400":GRAYS[400],"gray-500":GRAYS[500],"gray-600":GRAYS[600],"gray-700":GRAYS[700],"gray-800":GRAYS[800],"gray-900":GRAYS[900],},light:{primary:"#714b67",secondary:"#74b4b9",amber:"#f59e0b","amber-900":"#fef3c7",blue:"#3b82f6","blue-900":"#dbeafe",cyan:"#0891b2","cyan-900":"#e0f2fe",emerald:"#047857","emerald-900":"#ecfdf5",gray:GRAYS[400],lime:"#84cc16","lime-900":"#f7fee7",orange:"#ea580c","orange-900":"#ffedd5",purple:"#581c87","purple-900":"#f3e8ff",rose:"#9f1239","rose-900":"#fecdd3",bg:GRAYS[100],text:GRAYS[900],"status-bg":GRAYS[300],"link-text-hover":"var(--primary)","btn-bg":"#714b67","btn-bg-hover":"#624159","btn-text":"#ffffff","bg-result":"rgba(255, 255, 255, 0.6)","border-result":GRAYS[300],"border-search":"#d8dadd","shadow-opacity":0.1,"bg-report":"#ffffff","text-report":"#202124","border-report":"#f0f0f0","bg-report-error":"#fff0f0","text-report-error":"#ff0000","border-report-error":"#ffd6d6","text-report-number":"#1a1aa6","text-report-string":"#c80000","text-report-key":"#881280","text-report-html-tag":"#881280","text-report-html-id":"#1a1aa8","text-report-html-class":"#994500",},dark:{primary:"#14b8a6",amber:"#fbbf24","amber-900":"#422006",blue:"#60a5fa","blue-900":"#172554",cyan:"#22d3ee","cyan-900":"#083344",emerald:"#34d399","emerald-900":"#064e3b",gray:GRAYS[500],lime:"#bef264","lime-900":"#365314",orange:"#fb923c","orange-900":"#431407",purple:"#a855f7","purple-900":"#3b0764",rose:"#fb7185","rose-900":"#4c0519",bg:GRAYS[900],text:GRAYS[100],"status-bg":GRAYS[700],"btn-bg":"#00dac5","btn-bg-hover":"#00c1ae","btn-text":"#000000","bg-result":"rgba(0, 0, 0, 0.5)","border-result":GRAYS[600],"border-search":"#3c3f4c","shadow-opacity":0.4,"bg-report":"#202124","text-report":"#e8eaed","border-report":"#3a3a3a","bg-report-error":"#290000","text-report-error":"#ff8080","border-report-error":"#5c0000","text-report-number":"#9980ff","text-report-string":"#f28b54","text-report-key":"#5db0d7","text-report-html-tag":"#5db0d7","text-report-html-id":"#f29364","text-report-html-class":"#9bbbdc",},};const DEBUG_NAMESPACE="hoot";const isError=typeof Error.isError==="function"?Error.isError:polyfillIsError;const interactionBus=new EventTarget();const preferredColorScheme=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";__exports.addInteractionListener=addInteractionListener;function addInteractionListener(types,callback){for(const type of types){interactionBus.addEventListener(type,callback);}
return function removeInteractionListener(){for(const type of types){interactionBus.removeEventListener(type,callback);}};}
__exports.dispatchInteraction=dispatchInteraction;function dispatchInteraction(type,name,alias,args,returnValue){interactionBus.dispatchEvent(new CustomEvent(type,{detail:[name,alias,args,returnValue],}));return returnValue;}
__exports.exposeHelpers=exposeHelpers;function exposeHelpers(...helpers){let nameSpaceIndex=1;let nameSpace=DEBUG_NAMESPACE;while(nameSpace in globalThis){nameSpace=`${DEBUG_NAMESPACE}${nameSpaceIndex++}`;}
globalThis[nameSpace]=new HootDebugHelpers(...helpers);return nameSpace;}
__exports.getAllColors=getAllColors;function getAllColors(scheme){return scheme?COLORS[scheme]:COLORS;}
__exports.getColorHex=getColorHex;function getColorHex(varName){return COLORS[preferredColorScheme][varName];}
__exports.getPreferredColorScheme=getPreferredColorScheme;function getPreferredColorScheme(){return preferredColorScheme;}
__exports.getTag=getTag;function getTag(node){return node?.nodeName?.toLowerCase()||"";}
__exports.interactor=interactor;function interactor(type,fn){return $assign(makeInteractorFn(type,fn,fn.name),{as(alias){return makeInteractorFn(type,fn,fn.name,alias);},get silent(){return fn;},});}
__exports.isFirefox=isFirefox;function isFirefox(){return/firefox/i.test($userAgent);}
Array.isArray;__exports.isPromise=isPromise;function isPromise(instance){return instance&&typeof instance.then==="function";}
__exports.isInstanceOf=isInstanceOf;function isInstanceOf(instance,...classes){if(!classes.length){return instance instanceof classes[0];}
if(!instance||Object(instance)!==instance){return false;}
for(const cls of classes){if(instance instanceof cls){return true;}
const targetName=cls.name;if(!targetName){return false;}
if(targetName==="Array"){return $isArray(instance);}
if(targetName==="Error"){return isError(instance);}
if($toString.call(instance)===`[object ${targetName}]`){return true;}
let{constructor}=instance;while(constructor){if(constructor.name===targetName){return true;}
constructor=$getPrototypeOf(constructor);}}
return false;}
__exports.isIterable=isIterable;function isIterable(object){return!!(object&&typeof object==="object"&&object[Symbol.iterator]);}
__exports.parseRegExp=parseRegExp;function parseRegExp(value,options){const regexParams=value.match(R_REGEX);if(regexParams){const unified=regexParams[1].replace(R_WHITE_SPACE,"\\s+");const flag=regexParams[2];try{return new RegExp(unified,flag);}catch(error){if(isInstanceOf(error,SyntaxError)&&options?.safe){return value;}else{throw error;}}}
return value;}
__exports.toSelector=toSelector;function toSelector(node,options){const tagName=getTag(node);const id=node.id?`#${node.id}`:"";const classNames=node.classList?[...node.classList].map((className)=>`.${className}`):[];if(options?.raw){return{tagName,id,classNames};}else{return[tagName,id,...classNames].join("");}}
const HootDebugHelpers=__exports.HootDebugHelpers=class HootDebugHelpers{constructor(...helpers){$assign(this,...helpers);}}
const REGEX_MARKER=__exports.REGEX_MARKER="/";const R_REGEX=__exports.R_REGEX=new RegExp(`^${REGEX_MARKER}(.*)${REGEX_MARKER}([dgimsuvy]+)?$`);const R_WHITE_SPACE=__exports.R_WHITE_SPACE=/\s+/g;return __exports;});;

/* /web_tour/static/src/js/tour_step.js */
odoo.define('@web_tour/js/tour_step',['@web/session','@web/core/ui/ui_service','@odoo/hoot-dom','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const{utils}=require("@web/core/ui/ui_service");const hoot=require("@odoo/hoot-dom");const{pick}=require("@web/core/utils/objects");const TourStep=__exports.TourStep=class TourStep{constructor(data,tour){Object.assign(this,data);this.tour=tour;}
get active(){this.checkHasTour();const mode=this.tour.mode;const isSmall=utils.isSmall();const standardKeyWords=["enterprise","community","mobile","desktop","auto","manual"];const isActiveArray=Array.isArray(this.isActive)?this.isActive:[];if(isActiveArray.length===0){return true;}
const selectors=isActiveArray.filter((key)=>!standardKeyWords.includes(key));if(selectors.length){for(const selector of selectors){const el=hoot.queryFirst(selector);if(!el){return false;}}}
const checkMode=isActiveArray.includes(mode)||(!isActiveArray.includes("manual")&&!isActiveArray.includes("auto"));const edition=(session.server_version_info||"").at(-1)==="e"?"enterprise":"community";const checkEdition=isActiveArray.includes(edition)||(!isActiveArray.includes("enterprise")&&!isActiveArray.includes("community"));const onlyForMobile=isActiveArray.includes("mobile")&&isSmall;const onlyForDesktop=isActiveArray.includes("desktop")&&!isSmall;const checkDevice=onlyForMobile||onlyForDesktop||(!isActiveArray.includes("mobile")&&!isActiveArray.includes("desktop"));return checkEdition&&checkDevice&&checkMode;}
checkHasTour(){if(!this.tour){throw new Error(`TourStep instance must have a tour`);}}
get describeMe(){this.checkHasTour();return(`[${this.index + 1}/${this.tour.steps.length}] Tour ${this.tour.name} → Step `+
(this.content?`${this.content} (trigger: ${this.trigger})`:this.trigger));}
get stringify(){return(JSON.stringify(pick(this,"isActive","content","trigger","run","tooltipPosition","timeout","expectUnloadPage"),(_key,value)=>{if(typeof value==="function"){return"[function]";}else{return value;}},2)+",");}}
return __exports;});;

/* /web_tour/static/src/js/tour_automatic/tour_automatic.js */
odoo.define('@web_tour/js/tour_automatic/tour_automatic',['@odoo/hoot-dom','@web/../lib/hoot-dom/helpers/events','@web/core/browser/browser','@web/core/macro','@web/core/transition','@web_tour/js/tour_automatic/tour_step_automatic','@web_tour/js/tour_state'],function(require){'use strict';let __exports={};const hootDom=require("@odoo/hoot-dom");const{enableEventLogs,setupEventActions}=require("@web/../lib/hoot-dom/helpers/events");const{browser}=require("@web/core/browser/browser");const{Macro}=require("@web/core/macro");const{config:transitionConfig}=require("@web/core/transition");const{TourStepAutomatic}=require("@web_tour/js/tour_automatic/tour_step_automatic");const{tourState}=require("@web_tour/js/tour_state");const TourAutomatic=__exports.TourAutomatic=class TourAutomatic{mode="auto";allowUnload=true;constructor(data){Object.assign(this,data);this.steps=this.steps.map((step,index)=>new TourStepAutomatic(step,this,index));this.config=tourState.getCurrentConfig()||{};}
get currentIndex(){return tourState.getCurrentIndex();}
get currentStep(){return this.steps[this.currentIndex];}
get debugMode(){return this.config.debug!==false;}
start(){setupEventActions(document.createElement("div"),{allowSubmit:true});enableEventLogs(this.debugMode);const{delayToCheckUndeterminisms,stepDelay}=this.config;const macroSteps=this.steps.filter((step)=>step.index>=this.currentIndex).flatMap((step)=>[{action:async()=>{if(this.debugMode){console.groupCollapsed(step.describeMe);console.log(step.stringify);if(stepDelay>0){await hootDom.delay(stepDelay);}
if(step.break){debugger;}}else{console.log(step.describeMe);}},},{trigger:step.trigger?()=>step.findTrigger():null,timeout:step.pause&&this.debugMode?9999999:step.timeout||this.timeout||10000,action:async(trigger)=>{if(delayToCheckUndeterminisms>0){await step.checkForUndeterminisms(trigger,delayToCheckUndeterminisms);}
this.allowUnload=false;if(!step.skipped&&step.expectUnloadPage){this.allowUnload=true;setTimeout(()=>{const message=`
                                    The key { expectUnloadPage } is defined but page has not been unloaded within 20000 ms.
                                    You probably don't need it.
                                `.replace(/^\s+/gm,"");this.throwError(message);},20000);}
await step.doAction();if(this.debugMode){console.log(trigger);if(step.skipped){console.log("This step has been skipped");}else{console.log("This step has run successfully");}
console.groupEnd();if(step.pause){await this.pause();}}
tourState.setCurrentIndex(step.index+1);if(this.allowUnload){return"StopTheMacro!";}},},]);const end=()=>{delete window[hootNameSpace];transitionConfig.disabled=false;tourState.clear();window.addEventListener("error",(ev)=>{ev.preventDefault();ev.stopImmediatePropagation();},true);window.addEventListener("unhandledrejection",(ev)=>{ev.preventDefault();ev.stopImmediatePropagation();},true);};this.macro=new Macro({name:this.name,steps:macroSteps,onError:({error})=>{if(error.type==="Timeout"){this.throwError(...this.currentStep.describeWhyIFailed,error.message);}else{this.throwError(error.message);}
end();},onComplete:()=>{browser.console.log("tour succeeded");const succeeded=`║ TOUR ${this.name} SUCCEEDED ║`;const msg=[succeeded];msg.unshift("╔"+"═".repeat(succeeded.length-2)+"╗");msg.push("╚"+"═".repeat(succeeded.length-2)+"╝");browser.console.log(`\n\n${msg.join("\n")}\n`);end();},});const beforeUnloadHandler=()=>{if(!this.allowUnload){const message=`
                    Be sure to use { expectUnloadPage: true } for any step
                    that involves firing a beforeUnload event.
                    This avoid a non-deterministic behavior by explicitly stopping
                    the tour that might continue before the page is unloaded.
                `.replace(/^\s+/gm,"");this.throwError(message);}};window.addEventListener("beforeunload",beforeUnloadHandler);if(this.debugMode&&this.currentIndex===0){debugger;}
transitionConfig.disabled=true;const hootNameSpace=hootDom.exposeHelpers(hootDom);console.debug(`Hoot DOM helpers available from \`window.${hootNameSpace}\``);this.macro.start();}
get describeWhereIFailed(){const offset=3;const start=Math.max(this.currentIndex-offset,0);const end=Math.min(this.currentIndex+offset,this.steps.length-1);const result=[];for(let i=start;i<=end;i++){const step=this.steps[i];const stepString=step.stringify;const text=[stepString];if(i===this.currentIndex){const line="-".repeat(10);const failing_step=`${line} FAILED: ${step.describeMe} ${line}`;text.unshift(failing_step);text.push("-".repeat(failing_step.length));}
result.push(...text);}
return result.join("\n");}
throwError(...args){console.groupEnd();tourState.setCurrentTourOnError();browser.console.error([`FAILED: ${this.currentStep.describeMe}.`,...args].join("\n"));browser.console.dir(this.describeWhereIFailed);if(this.debugMode){debugger;}}
async pause(){const styles=["background: black; color: white; font-size: 14px","background: black; color: orange; font-size: 14px",];console.log(`%cTour is paused. Use %cplay()%c to continue.`,styles[0],styles[1],styles[0]);await new Promise((resolve)=>{window.play=()=>{resolve();delete window.play;};});}}
return __exports;});;

/* /web_tour/static/src/js/tour_automatic/tour_helpers_hoot.js */
odoo.define('@web_tour/js/tour_automatic/tour_helpers_hoot',['@odoo/hoot-dom','@web/core/utils/patch','@web_tour/js/tour_automatic/tour_helpers'],function(require){'use strict';let __exports={};const hoot=require("@odoo/hoot-dom");const{patch}=require("@web/core/utils/patch");const{TourHelpers}=require("@web_tour/js/tour_automatic/tour_helpers");patch(TourHelpers.prototype,{async check(selector){const element=this._get_action_element(selector);await hoot.check(element);},async clear(selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.clear();},async click(selector,options={interactive:false}){const element=this._get_action_element(selector);await hoot.click(element,options);},async dblclick(selector){const element=this._get_action_element(selector);await hoot.dblclick(element);},async drag_and_drop(selector,options){if(typeof options!=="object"){options={position:"top",relative:true};}
const dragEffectDelay=async()=>{await hoot.animationFrame();await hoot.delay(this.delay);};const element=this.anchor;const{drop,moveTo}=await hoot.drag(element);await dragEffectDelay();await hoot.hover(element,{position:{top:20,left:20,},relative:true,});await dragEffectDelay();const target=await hoot.waitFor(selector,{visible:true,timeout:1000,});await moveTo(target,options);await dragEffectDelay();await drop(target,options);await dragEffectDelay();},async edit(text,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.edit(text);},async editor(text,selector){const element=this._get_action_element(selector);const InEditor=Boolean(element.closest(".odoo-editor-editable"));if(!InEditor){throw new Error("run 'editor' always on an element in an editor");}
await hoot.click(element);this._set_range(element,"start");await hoot.keyDown("_");element.textContent=text;await hoot.manuallyDispatchProgrammaticEvent(element,"input");this._set_range(element,"stop");await hoot.keyUp("_");await hoot.manuallyDispatchProgrammaticEvent(element,"change");},async fill(value,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.fill(value);},async hover(selector,options){const element=this._get_action_element(selector);await hoot.hover(element,options);},async range(value,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.setInputRange(element,value);},async press(...args){await hoot.press(args.flatMap((arg)=>typeof arg==="string"&&arg.split("+")));},async select(value,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.select(value,{target:element});},async selectByIndex(index,selector){const element=this._get_action_element(selector);await hoot.click(element);const value=hoot.queryValue(`option:eq(${index})`,{root:element});if(value){await hoot.select(value,{target:element});await hoot.manuallyDispatchProgrammaticEvent(element,"input");}},async selectByLabel(contains,selector){const element=this._get_action_element(selector);await hoot.click(element);const values=hoot.queryAllValues(`option:contains(${contains})`,{root:element});await hoot.select(values,{target:element});},async uncheck(selector){const element=this._get_action_element(selector);await hoot.uncheck(element);},async goToUrl(url){const linkEl=document.createElement("a");linkEl.href=url;await hoot.click(linkEl);},async canvasNotEmpty(selector){const canvas=this._get_action_element(selector);if(canvas.tagName.toLowerCase()!=="canvas"){throw new Error(`canvasNotEmpty is only suitable for canvas elements.`);}
await hoot.waitUntil(()=>{const context=canvas.getContext("2d");const imageData=context.getImageData(0,0,canvas.width,canvas.height);const pixels=new Uint32Array(imageData.data.buffer);return pixels.some((pixel)=>pixel!==0);});},_get_action_element(selector){if(typeof selector==="string"&&selector.length){const nodes=hoot.queryAll(selector);return nodes.find(hoot.isVisible)||nodes.at(0);}else if(typeof selector==="object"&&Boolean(selector?.nodeType)){return selector;}
return this.anchor;},_set_range(element,start_or_stop){function _node_length(node){if(node.nodeType===Node.TEXT_NODE){return node.nodeValue.length;}else{return node.childNodes.length;}}
const selection=element.ownerDocument.getSelection();selection.removeAllRanges();const range=new Range();let node=element;let length=0;if(start_or_stop==="start"){while(node.firstChild){node=node.firstChild;}}else{while(node.lastChild){node=node.lastChild;}
length=_node_length(node);}
range.setStart(node,length);range.setEnd(node,length);selection.addRange(range);},queryAll(target,options){return hoot.queryAll(target,options);},queryFirst(target,options){return hoot.queryFirst(target,options);},queryOne(target,options){return hoot.queryOne(target,options);},waitFor(target,options){return hoot.waitFor(target,options);},waitUntil(predicate,options){return hoot.waitUntil(predicate,options);},animationFrame(...args){return hoot.animationFrame(...args);},});return __exports;});;

/* /web_tour/static/src/js/tour_automatic/tour_step_automatic.js */
odoo.define('@web_tour/js/tour_automatic/tour_step_automatic',['@web_tour/js/tour_state','@odoo/hoot-dom','@web_tour/js/utils/tour_utils','@web_tour/js/tour_automatic/tour_helpers','@web_tour/js/tour_step','@web/core/utils/xml','@web/core/macro'],function(require){'use strict';let __exports={};const{tourState}=require("@web_tour/js/tour_state");const hoot=require("@odoo/hoot-dom");const{serializeChanges,serializeMutation}=require("@web_tour/js/utils/tour_utils");const{TourHelpers}=require("@web_tour/js/tour_automatic/tour_helpers");const{TourStep}=require("@web_tour/js/tour_step");const{getTag}=require("@web/core/utils/xml");const{MacroMutationObserver}=require("@web/core/macro");async function waitForMutations(target=document,timeout=1000/16){return new Promise((resolve)=>{let observer;let timer;const mutationList=[];function onMutation(mutations){mutationList.push(...(mutations||[]));clearTimeout(timer);timer=setTimeout(()=>{observer.disconnect();resolve(mutationList);},timeout);}
observer=new MacroMutationObserver(onMutation);observer.observe(target);onMutation([]);});}
const TourStepAutomatic=__exports.TourStepAutomatic=class TourStepAutomatic extends TourStep{skipped=false;error="";constructor(data,tour,index){super(data,tour);this.index=index;this.tourConfig=tourState.getCurrentConfig();}
async checkForUndeterminisms(initialElement,delay){if(delay<=0||!initialElement){return;}
const tagName=initialElement.tagName?.toLowerCase();if(["body","html"].includes(tagName)||!tagName){return;}
const snapshot=initialElement.cloneNode(true);const mutations=await waitForMutations(initialElement,delay);let reason;if(!hoot.isVisible(initialElement)){reason=`Initial element is no longer visible`;}else if(!initialElement.isEqualNode(snapshot)){reason=`Initial element has changed:\n`+
JSON.stringify(serializeChanges(snapshot,initialElement),null,2);}else if(mutations.length){const changes=[...new Set(mutations.map(serializeMutation))];reason=`Initial element has mutated ${mutations.length} times:\n`+
JSON.stringify(changes,null,2);}
if(reason){throw new Error(`Potential non deterministic behavior found in ${delay}ms for trigger ${this.trigger}.\n${reason}`);}}
get describeWhyIFailed(){const errors=[];if(this.element){errors.push(`Element has been found.`);if(this.isUIBlocked){errors.push("BUT: DOM is blocked by UI.");}
if(!this.elementIsInModal){errors.push(`BUT: It is not allowed to do action on an element that's below a modal.`);}
if(!this.elementIsEnabled){errors.push(`BUT: Element is not enabled. TIP: You can use :enable to wait the element is enabled before doing action on it.`);}
if(!this.parentFrameIsReady){errors.push(`BUT: parent frame is not ready ([is-ready='false']).`);}}else{const checkElement=hoot.queryFirst(this.trigger);if(checkElement){errors.push(`Element has been found.`);errors.push(`BUT: Element is not visible. TIP: You can use :not(:visible) to force the search for an invisible element.`);}else{errors.push(`Element (${this.trigger}) has not been found.`);}}
return errors;}
async doAction(){if(this.skipped){return false;}
const actionHelper=new TourHelpers(this.element);if(typeof this.run==="function"){return await this.run.call({anchor:this.element},actionHelper);}else if(typeof this.run==="string"){let lastResult=null;for(const todo of this.run.split("&&")){const m=String(todo).trim().match(/^(?<action>\w*) *\(? *(?<arguments>.*?)\)?$/);lastResult=await actionHelper[m.groups?.action](m.groups?.arguments);}
return lastResult;}}
findTrigger(){if(!this.active){this.skipped=true;return true;}
const visible=!/:(hidden|visible)\b/.test(this.trigger);this.element=hoot.queryFirst(this.trigger,{visible});if(this.element){return!this.isUIBlocked&&this.elementIsEnabled&&this.elementIsInModal&&this.parentFrameIsReady?this.element:false;}
return false;}
get isUIBlocked(){return(document.body.classList.contains("o_ui_blocked")||document.querySelector(".o_blockUI")||document.querySelector(".o_is_blocked"));}
get parentFrameIsReady(){if(this.trigger.match(/\[is-ready=(true|false)\]/)){return true;}
const parentFrame=hoot.getParentFrame(this.element);return parentFrame&&parentFrame.contentDocument.body.hasAttribute("is-ready")?parentFrame.contentDocument.body.getAttribute("is-ready")==="true":true;}
get elementIsInModal(){if(this.hasAction){const overlays=hoot.queryFirst(".popover, .o-we-command, .o-we-toolbar, .o_notification");const modal=hoot.queryFirst(".modal:visible:not(.o_inactive_modal):last");if(modal&&!overlays&&!this.trigger.startsWith("body")){return(modal.contains(hoot.getParentFrame(this.element))||modal.contains(this.element));}}
return true;}
get elementIsEnabled(){const isTag=(array)=>array.includes(getTag(this.element,true));if(this.hasAction){if(isTag(["input","textarea"])){return hoot.isEditable(this.element);}else if(isTag(["button","select"])){return!this.element.disabled;}}
return true;}
get hasAction(){return["string","function"].includes(typeof this.run)&&!this.skipped;}}
return __exports;});;

/* /html_editor/static/tests/tours/helpers/editor.js */
odoo.define('@html_editor/../tests/tours/helpers/editor',['@web/core/utils/patch'],function(require){'use strict';let __exports={};const{patch}=require("@web/core/utils/patch");const editorsWeakMap=__exports.editorsWeakMap=new WeakMap();const editorModule=odoo.loader.modules.get("@html_editor/editor");if(editorModule){const{Editor}=editorModule;patch(Editor.prototype,{attachTo(editable){editorsWeakMap.set(editable.ownerDocument,this);return super.attachTo(...arguments);},});}
__exports.setSelection=setSelection;function setSelection({anchorNode,anchorOffset,focusNode=anchorNode,focusOffset=anchorOffset,}){const selection=anchorNode.ownerDocument.getSelection();selection.setBaseAndExtent(anchorNode,anchorOffset,focusNode,focusOffset);}
return __exports;});;

/* /mail/static/tests/tours/activity_date_format_tour.js */
odoo.define('@mail/../tests/tours/activity_date_format_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("mail_activity_date_format",{steps:()=>[{trigger:"button:contains('Activity')",run:"click",},{trigger:".o_selection_badge span:contains('To-Do')",run:"click",},{trigger:"div[name='summary'] input",run:"edit Go Party",},{trigger:"button:contains('Save')",run:"click",},{trigger:".o-mail-Activity:contains('Go Party')",run:"click",},{trigger:".o-mail-Activity-info i",run:"click",},{trigger:".o-mail-Activity-details tr:contains('Created') td:contains('01/Jan/24 09:00:00 AM')",},{trigger:".o-mail-Activity-details tr:contains('Due on') td:contains('06/Jan/24')",},],});return __exports;});;

/* /mail/static/tests/tours/create_channel_tour.js */
odoo.define('@mail/../tests/tours/create_channel_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("can_create_channel_from_form_view",{steps:()=>[{trigger:".o-mail-DiscussSidebarChannel-itemName:contains(OdooBot)",run:"click",},{trigger:".o-mail-DiscussContent-threadName[title='OdooBot']",},{trigger:"button[title='View or join channels']:not(:visible)",run:"click"},{trigger:".o_control_panel_main_buttons button:contains('New')",run:"click",},{trigger:"div[name='name'] input",run:"edit Test channel",},{trigger:".breadcrumb-item:contains('OdooBot')",run:"click",},{trigger:".o-mail-DiscussSidebarChannel-itemName:contains('Test channel')",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_call_invitation_tour.js */
odoo.define('@mail/../tests/tours/discuss_call_invitation_tour',['@mail/discuss/core/common/channel_member_model','@web/core/registry','@web/../tests/helpers/utils'],function(require){'use strict';let __exports={};const{ChannelMember}=require("@mail/discuss/core/common/channel_member_model");const{registry}=require("@web/core/registry");const{patchWithCleanup}=require("@web/../tests/helpers/utils");registry.category("web_tour.tours").add("discuss_call_invitation.js",{steps:()=>{patchWithCleanup(ChannelMember,{CANCEL_CALL_INVITE_DELAY:1e6});return[{trigger:".o-discuss-CallInvitation"},{trigger:".o-mail-CallInvitation-avatar[title='View the bob (base.group_user) and john (base.group_user) channel']",},{trigger:".o-discuss-CallInvitation-channelName:contains('bob (base.group_user) and john (base.group_user)')",},{trigger:".o-discuss-CallInvitation-description:contains('Incoming call from bob (base.group_user)')",},{trigger:".o-discuss-CallInvitation-cameraPreview:not(:visible)",},{trigger:".o-discuss-CallInvitation button[title='Join Call']",},{trigger:".o-discuss-CallInvitation button[title='Reject']",},{trigger:".o-discuss-CallInvitation button[title='Show camera preview']",run:"click",},{trigger:".o-discuss-CallInvitation-cameraPreview",},{trigger:".o-discuss-CallInvitation-cameraPreview button[title='Turn camera on']",},{trigger:".o-discuss-CallInvitation-cameraPreview button[title='Unmute']",},{trigger:".o-discuss-CallInvitation-cameraPreview button[title='Video Settings']",run:"click",},{trigger:"label:contains('Blur background')",},{trigger:".o-discuss-CallInvitation button[title='Hide camera preview']",run:"click",},{trigger:".o-discuss-CallInvitation-cameraPreview:not(:visible)",},];},});return __exports;});;

/* /mail/static/tests/tours/discuss_channel_as_guest_tour.js */
odoo.define('@mail/../tests/tours/discuss_channel_as_guest_tour',['@web/core/registry','@web/../tests/utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{contains}=require("@web/../tests/utils");registry.category("web_tour.tours").add("discuss_channel_as_guest_tour.js",{steps:()=>[{content:"Channel secret token has been hidden on welcome page",trigger:".o-mail-WelcomePage",run(){if(!window.location.pathname.startsWith("/discuss/channel")){console.error("Channel secret token is still present in URL.");}},},{content:"Click join",trigger:"button[title='Join Channel']",run:"click",},{content:"Check that we are on not in a call",trigger:"button[name='call']",},{content:"Check that we are on channel page",trigger:".o-mail-Thread",run:"press ctrl+k",},{trigger:".o_command_palette_search input",run:"fill @",},{trigger:".o-mail-DiscussCommand",async run(){await contains(".fa-hashtag",{parent:[".o-mail-DiscussCommand",{text:"Test channel"}],});await contains(".fa-user",{count:0});},},],});return __exports;});;

/* /mail/static/tests/tours/discuss_channel_call_action.js */
odoo.define('@mail/../tests/tours/discuss_channel_call_action',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("discuss_channel_call_action.js",{steps:()=>[{content:"Check that the call has started",trigger:".o-discuss-Call",},{content:"Check that current user is in call ('disconnect' button visible)",trigger:"button[title='Disconnect']",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_channel_call_public_tour.js */
odoo.define('@mail/../tests/tours/discuss_channel_call_public_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("discuss_channel_call_public_tour.js",{steps:()=>[{content:"The call does not start on the welcome page",trigger:".o-mail-WelcomePage",async run(){await new Promise((r)=>setTimeout(r,250));const rtcService=odoo.__WOWL_DEBUG__.root.env.services["discuss.rtc"];if(rtcService?.selfSession||rtcService?.state.hasPendingRequest){console.error("The call should not have started.");}},},{content:"Click join",trigger:"button[title='Join Channel']",run:"click",},{content:"Check that the call has started",trigger:".o-discuss-Call",},{content:"Check that current user is in call ('disconnect' button visible)",trigger:"button[title='Disconnect']",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_channel_meeting_view_tour.js */
odoo.define('@mail/../tests/tours/discuss_channel_meeting_view_tour',['@web/core/browser/browser','@web/core/registry','@web/../tests/utils'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const{dragenterFiles}=require("@web/../tests/utils");const CLICK_ON_CHAT_STEP="click-on-chat-action";function getMeetingViewTourSteps({inWelcomePage=false}={}){const steps=[{trigger:".o-mail-Meeting"},{trigger:".o-mail-Meeting [title='Invite People']",run:"click",},{trigger:".o-mail-Meeting .o-mail-ActionPanel:contains('Invite people')"},{trigger:".o-mail-Meeting [title='Invite People']",run:"click",},{trigger:".o-mail-Meeting:not(:has(.o-mail-ActionPanel))"},{trigger:".o-mail-Meeting [title='Invite People']",run:"click",},{trigger:".o-mail-Meeting .o-mail-ActionPanel:contains('Invite people')"},{trigger:".o-mail-Meeting [title='Chat']",run:"click",content:CLICK_ON_CHAT_STEP,},{trigger:".o-mail-Meeting .o-mail-ActionPanel .o-mail-Thread:contains('john (base.group_user) and bob (base.group_user)')",},{trigger:".o-mail-Message[data-persistent]:contains('Hello everyone!')",run:"hover && click .o-mail-Message-actions button[title='Expand']",},{trigger:".o-dropdown-item:contains('Mark as Unread')",run:"click",},{trigger:".o-mail-Meeting [title='Chat']:has(.badge:contains(1))"},{trigger:".o-mail-Thread-banner span:contains('Mark as Read')",run:"click",},{trigger:".o-mail-Meeting [title='Chat']:not(:has(.badge))",async run({waitFor}){const files=[new File(["hi there"],"file2.txt",{type:"text/plain"})];await dragenterFiles(".o-mail-Meeting .o-mail-ActionPanel",files);await waitFor(".o-Dropzone",{only:true});},},{trigger:".o-mail-Meeting [title='Close panel']",run:"click",},{trigger:".o-mail-Meeting:not(:has(.o-mail-ActionPanel))"},{trigger:".o-mail-Meeting [title='Exit Fullscreen']",run:"click",},{trigger:"body:not(:has(.o-mail-Meeting))"},];if(inWelcomePage){steps.unshift({trigger:"[title='Join Channel']",run:"click"});}
return steps;}
registry.category("web_tour.tours").add("discuss.meeting_view_tour",{steps:()=>{browser.localStorage.setItem("discuss_call_preview_join_mute","true");browser.localStorage.setItem("discuss_call_preview_join_video","false");const steps=getMeetingViewTourSteps();const clickOnChatIndex=steps.find((step)=>step.content===CLICK_ON_CHAT_STEP);steps.splice(clickOnChatIndex,0,{trigger:".o-mail-Composer.o-focused .o-mail-Composer-input",run:"edit Hello everyone!",},{trigger:".o-mail-Composer button[title='Send']:enabled",run:"click"});return steps;},}).add("discuss.meeting_view_public_tour",{steps:()=>getMeetingViewTourSteps({inWelcomePage:true}),});return __exports;});;

/* /mail/static/tests/tours/discuss_channel_public_tour.js */
odoo.define('@mail/../tests/tours/discuss_channel_public_tour',['@odoo/owl','@web/core/registry','@web/core/utils/urls','@web/../tests/utils'],function(require){'use strict';let __exports={};const{reactive}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{getOrigin}=require("@web/core/utils/urls");const{click,inputFiles}=require("@web/../tests/utils");const messageSelector=".o-mail-Message:has(.o-mail-Message-body:contains('cheese'))";const editedMessageSelector=".o-mail-Message:has(.o-mail-Message-body:contains('vegetables'))";registry.category("web_tour.tours").add("discuss_channel_public_tour.js",{steps:()=>[{trigger:".o-mail-Discuss",},{trigger:".o-mail-Thread",run(){if(!window.location.pathname.startsWith("/discuss/channel")){console.error("Channel secret token is still present in URL.");}
const errors=odoo.loader.findErrors();if(Object.keys(errors).length){console.error("Couldn't load all JS modules.",errors);}
document.body.classList.add("o_discuss_channel_public_modules_loaded");if(!document.title.includes(document.querySelector(".o-mail-DiscussContent-threadName")?.value)){console.error(`Tab title should match conversation name. Got "${
                            document.title
                        }" instead of "${
                            document.querySelector(".o-mail-DiscussContent-threadName")?.value
                        }".`);}},},{trigger:".o_discuss_channel_public_modules_loaded",},{trigger:".o-mail-Composer-input",run:"edit cheese",},{trigger:".o-mail-Composer button[title='More Actions']",run:"click"},{trigger:".dropdown-item:contains('Attach Files')",async run(){const text=new File(["hello, world"],"text.txt",{type:"text/plain"});await inputFiles(".o-mail-Composer .o_input_file",[text]);},},{trigger:".o-mail-AttachmentContainer:not(.o-isUploading):contains(text.txt)",},{trigger:".dropdown-item:contains('Attach Files')",async run(){await inputFiles(".o-mail-Composer .o_input_file",[new File([await(await fetch("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v5ThPwAG7wKklwQ/bwAAAABJRU5ErkJggg==")).blob(),],"image.png",{type:"image/png"}),]);},},{trigger:'.o-mail-AttachmentContainer:not(.o-isUploading)[title="image.png"]',async run({waitFor}){const store=odoo.__WOWL_DEBUG__.root.env.services["mail.store"];if(store.self_guest){const src=this.anchor.querySelector("img").src;const attachment=store["ir.attachment"].get((src.match("/web/image/([0-9]+)")||[]).at(-1));if(!attachment){throw new Error(`Attachment was not found from src: ${src}`);}
if(!attachment.raw_access_token){await new Promise((resolve)=>{const proxy=reactive(attachment,()=>{if(attachment.raw_access_token){resolve();}else{void proxy.raw_access_token;}});void proxy.raw_access_token;});}
await waitFor(`.o-mail-AttachmentContainer[title="image.png"] img[src="${getOrigin()}/web/image/${
                            attachment.id
                        }?access_token=${attachment.raw_access_token}&filename=image.png&unique=${
                            attachment.checksum
                        }"]`);}},},{trigger:".o-mail-Composer button[title='Send']:enabled",run:"click"},{trigger:`${messageSelector}[data-persistent]`,},{trigger:`${messageSelector} .o-mail-AttachmentContainer:contains("text.txt")`,},{trigger:messageSelector,run:`hover && click ${messageSelector} [title='Add a Reaction']`,},{trigger:".o-mail-QuickReactionMenu",run:()=>click("[title='Toggle Emoji Picker']"),},{trigger:".o-EmojiPicker .o-Emoji:contains('🙂')",run:"click",},{trigger:`${messageSelector} .o-mail-MessageReaction:contains('🙂')`,run:"click",},{trigger:`${messageSelector}:not(:has(.o-mail-MessageReaction:contains('🙂')))`,},{trigger:`${messageSelector}`,run:`hover && click ${messageSelector} [title='Expand']`,},{trigger:`.o-mail-Message-moreMenu [title='Edit'], ${messageSelector} [title='Edit']`,run:"click",},{trigger:".o-mail-Message .o-mail-Composer-input",run:"edit vegetables",},{trigger:".o-mail-Message .o-mail-Composer button[title='More Actions']",run:"click",},{trigger:".dropdown-item:contains('Attach Files')",async run(){const extratxt=new File(["hello 2"],"extra.txt",{type:"text/plain"});await inputFiles(".o-mail-Message .o_input_file",[extratxt]);},},{trigger:".o-mail-Message .o-mail-Composer .o-mail-AttachmentContainer:not(.o-isUploading):contains(extra.txt)",},{trigger:".o-mail-Message button:contains(save)",run:"click",},{trigger:editedMessageSelector,},{trigger:`${editedMessageSelector} .o-mail-AttachmentContainer:contains("text.txt")`,},{trigger:`${editedMessageSelector} .o-mail-AttachmentContainer:contains("extra.txt")`,},{trigger:`${editedMessageSelector} .o-mail-AttachmentContainer:contains("extra.txt") .o-mail-Attachment-unlink`,run:"click",},{trigger:".modal:contains(Confirmation) .btn:contains(Ok)",run:"click",},{trigger:`${editedMessageSelector}:not(:has(.o-mail-AttachmentContainer:contains("extra.txt")))`,},{trigger:"button[title='Search Messages']",run:"click",},{trigger:".o_searchview_input",run:"edit text.txt",},{trigger:"button[aria-label='Search button']",run:"click",},{trigger:`.o-mail-SearchMessagesPanel ${editedMessageSelector} .o-mail-AttachmentContainer:contains("text.txt")`,},],});return __exports;});;

/* /mail/static/tests/tours/discuss_configuration_tour.js */
odoo.define('@mail/../tests/tours/discuss_configuration_tour',['@web/core/registry','@web_tour/tour_utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_utils");registry.category("web_tour.tours").add("discuss_configuration_tour",{url:"/odoo",steps:()=>[stepUtils.showAppsMenuItem(),{trigger:'.o_app[data-menu-xmlid="mail.menu_root_discuss"]',run:"click",},{trigger:".o_main_navbar button:contains('Configuration')",run:"click",},{trigger:".dropdown-menu a:contains('Notification')",run:"click",},{trigger:"button:contains('All Messages')",run:"click",},{trigger:"button:contains('Mentions Only')",run:"click",},{trigger:"button:contains('Nothing')",run:"click",},{trigger:".modal-header button[aria-label='Close']",run:"click",},{trigger:".o_main_navbar button:contains('Configuration')",run:"click",},{trigger:".dropdown-menu a:contains('Voice & Video')",run:"click",},{trigger:"select[name='inputDevice']",},{trigger:"button:contains('Voice Detection')",run:"click",},{trigger:"span:contains('Voice detection sensitivity')",},{trigger:"button:contains('Push to Talk')",run:"click",},{trigger:"label:contains('Push-to-talk key')",},{trigger:"label:contains('Delay after releasing push-to-talk')",},{trigger:"input[aria-label='Show video participants only']",},{trigger:"input[aria-label='Blur video background']",run:"click",},{trigger:"label:contains('Background blur intensity')",},{trigger:"label:contains('Edge blur intensity')",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_go_back_to_thread_from_breadcrumbs_tour.js */
odoo.define('@mail/../tests/tours/discuss_go_back_to_thread_from_breadcrumbs_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("discuss_go_back_to_thread_from_breadcrumbs.js",{steps:()=>[{trigger:".o-mail-DiscussContent-threadName[title='Inbox']"},{trigger:".o-mail-DiscussSidebar-item:contains('Starred messages')",run:"click"},{trigger:"button[title='View or join channels']:not(:visible)",run:"click"},{trigger:".breadcrumb-item:contains('Starred messages')",run:"click"},{trigger:".o-mail-DiscussContent-threadName[title='Starred messages']"},],});return __exports;});;

/* /mail/static/tests/tours/discuss_invite_by_email_tour.js */
odoo.define('@mail/../tests/tours/discuss_invite_by_email_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("discuss.invite_by_email",{steps:()=>[{trigger:".o-discuss-ChannelMemberList"},{trigger:"button[title='Invite People']",run:"click",},{trigger:".o-discuss-ChannelInvitation-search[placeholder='Invite people or email']",run:"edit john@test.com",},{trigger:".o-discuss-ChannelInvitation-selectable:contains('john (base.group_user)')",async run({waitFor,click}){await waitFor(".o-discuss-ChannelInvitation-selectable",{only:true,timeout:5000,});await click();},},{trigger:".o-discuss-ChannelInvitation-selectedList :contains('john (base.group_user)')",},{trigger:".o-discuss-ChannelInvitation-search",run:"edit unknown_email@test.com",},{trigger:".o-discuss-ChannelInvitation-selectable:contains('unknown_email@test.com')",run:"click",},{trigger:".o-discuss-ChannelInvitation-selectedList :contains('unknown_email@test.com')",},{trigger:"button:contains(Invite to Group Chat)",run:"click",},{trigger:"body:not(:has(.o-mail-ActionPanel))",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_mention_suggestions_group_restricted_channel.js */
odoo.define('@mail/../tests/tours/discuss_mention_suggestions_group_restricted_channel',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("discuss_mention_suggestions_group_restricted_channel.js",{steps:()=>[{trigger:".o-mail-DiscussContent-threadName[title='R&D Channel']"},{trigger:".o-mail-Composer-input",run:"edit @"},{trigger:".o-mail-Composer-suggestion:count(3)"},{content:"Suggest channel member not in R&D group",trigger:".o-mail-Composer-suggestion strong:text(Consultant User)",},{content:"Suggest non-channel member in R&D group",trigger:".o-mail-Composer-suggestion strong:text(Dev User)",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_sidebar_in_public_page_tour.js */
odoo.define('@mail/../tests/tours/discuss_sidebar_in_public_page_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("sidebar_in_public_page_tour",{steps:()=>[{trigger:".o-mail-DiscussContent-header [title='Channel 1']",},{trigger:".o-mail-DiscussSidebarChannel:contains(Channel 1).o-active",},{trigger:".o-mail-DiscussSidebarChannel:contains(Channel 2)",run:"click",},{trigger:".o-mail-DiscussContent-header [title='Channel 2']",},{trigger:".o-mail-DiscussSidebarChannel:contains(Channel 2).o-active",run(){history.back();},},{trigger:".o-mail-DiscussContent-header [title='Channel 1']",},{trigger:".o-mail-DiscussSidebarChannel:contains(Channel 1).o-active",run(){history.forward();},},{trigger:".o-mail-DiscussContent-header [title='Channel 2']",},{trigger:".o-mail-DiscussSidebarChannel:contains(Channel 2).o-active",},{content:"Open channel actions",trigger:".o-mail-DiscussSidebarChannel:contains(Channel 2).o-active",run:"hover && click [title='Channel Actions']",},{trigger:".o-dropdown-item:contains('Invite People')",run:"click",},],});return __exports;});;

/* /mail/static/tests/tours/discuss_sub_channel_search_tour.js */
odoo.define('@mail/../tests/tours/discuss_sub_channel_search_tour',['@mail/discuss/core/public_web/sub_channel_list','@odoo/owl','@web/core/registry','@web/core/utils/concurrency','@web/core/utils/patch','@web/core/utils/reactive','@web/../tests/utils'],function(require){'use strict';let __exports={};const{SubChannelList}=require("@mail/discuss/core/public_web/sub_channel_list");const{status}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{Deferred}=require("@web/core/utils/concurrency");const{patch}=require("@web/core/utils/patch");const{effect}=require("@web/core/utils/reactive");const{contains,dragenterFiles,dropFiles,scroll}=require("@web/../tests/utils");let waitForLoadMoreToDisappearDef;registry.category("web_tour.tours").add("test_discuss_sub_channel_search",{steps:()=>[{trigger:"body",run(){patch(SubChannelList.prototype,{setup(){super.setup(...arguments);effect((state)=>{if(status(this)==="destroyed"){return;}
if(!state.isVisible){waitForLoadMoreToDisappearDef?.resolve();}},[this.loadMoreState]);},});},},{trigger:"button[title='Threads']",run:"click",},{trigger:".o-mail-SubChannelList",async run(){for(let i=99;i>69;i--){await contains(".o-mail-SubChannelPreview",{text:`Sub Channel ${i}`,});await contains(".o-mail-SubChannelPreview",{count:30});}},},{trigger:".o-mail-ActionPanel:has(.o-mail-SubChannelList) .o_searchview_input",run:"edit Sub Channel 10",},{trigger:".o-mail-ActionPanel:has(.o-mail-SubChannelList) button[aria-label='Search button']",run:"click",},{trigger:".o-mail-SubChannelPreview:contains(Sub Channel 10)",async run(){await contains(".o-mail-SubChannelPreview",{count:1});waitForLoadMoreToDisappearDef=new Deferred();},},{trigger:".o_searchview_input",run:"clear",},{trigger:".o-mail-SubChannelPreview:contains(Sub Channel 99)",async run(){await contains(".o-mail-SubChannelPreview",{count:31});for(let i=99;i>69;i--){await contains(".o-mail-SubChannelPreview",{text:`Sub Channel ${i}`,});}
await contains(".o-mail-SubChannelPreview",{text:`Sub Channel 10`});await waitForLoadMoreToDisappearDef;waitForLoadMoreToDisappearDef=new Deferred();await scroll(".o-mail-ActionPanel:has(.o-mail-SubChannelList)","bottom");},},{trigger:".o-mail-SubChannelPreview:contains(Sub Channel 40)",async run(){await contains(".o-mail-SubChannelPreview",{count:61});for(let i=99;i>39;i--){await contains(".o-mail-SubChannelPreview",{text:`Sub Channel ${i}`,});}
await waitForLoadMoreToDisappearDef;waitForLoadMoreToDisappearDef=new Deferred();await scroll(".o-mail-ActionPanel:has(.o-mail-SubChannelList)","bottom");},},{trigger:".o-mail-SubChannelPreview:contains(Sub Channel 11)",async run(){await contains(".o-mail-SubChannelPreview",{count:90});for(let i=99;i>9;i--){await contains(".o-mail-SubChannelPreview",{text:`Sub Channel ${i}`,});}
await waitForLoadMoreToDisappearDef;await scroll(".o-mail-ActionPanel:has(.o-mail-SubChannelList)","bottom");},},{trigger:".o-mail-SubChannelPreview:contains(Sub Channel 0)",async run(){await contains(".o-mail-SubChannelPreview",{count:100});for(let i=99;i>0;i--){await contains(".o-mail-SubChannelPreview",{text:`Sub Channel ${i}`,});}},},],});registry.category("web_tour.tours").add("create_thread_for_attachment_without_body",{steps:()=>[{content:"Open general channel",trigger:'.o-mail-DiscussSidebarChannel-itemName:contains("general")',run:"click",},{content:"Drop a file",trigger:".o-mail-DiscussContent-main",async run(){const files=[new File(["hi there"],"file2.txt",{type:"text/plain"})];await dragenterFiles(".o-mail-DiscussContent-main",files);await dropFiles(".o-Dropzone",files);},},{trigger:'.o-mail-AttachmentContainer:not(.o-isUploading):contains("file2.txt")',},{content:"Click on send button",trigger:".o-mail-Composer-mainActions [title='Send']:enabled",run:"click",},{content:"Hover on attachment",trigger:'.o-mail-Message:not(:has(.o-mail-Message-pendingProgress)) .o-mail-AttachmentContainer:contains("file2.txt")',run:"hover",},{content:"Click on expand button",trigger:'.o-mail-Message [title="Expand"]',run:"click",},{content:"Create a new thread",trigger:'.o-dropdown-item:contains("Create Thread")',run:"click",},{content:"Check a new thread is created",trigger:'.o-mail-Discuss:contains("New Thread")',},],});return __exports;});;

/* /mail/static/tests/tours/mail_activity_schedule_from_chatter.js */
odoo.define('@mail/../tests/tours/mail_activity_schedule_from_chatter',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("mail_activity_schedule_from_chatter",{steps:()=>[{trigger:"button:contains('Activity')",run:"click",},{trigger:".o_selection_badge span:contains('Call')",run:"click",},{trigger:".o_selection_badge.active span:contains('Call')",},{trigger:".o_selection_badge span:contains('To-Do')",run:"click",},{trigger:"div[name='summary'] input",run:"edit Play Mario Party",},{trigger:"button:contains('Save')",run:"click",},{trigger:".o-mail-Activity:contains('Play Mario Party')",run:"click",},{trigger:"button:contains('Activity')",run:"click",},{trigger:"div[name='summary'] input",run:"edit Play Mario Kart",},{trigger:"button.btn.btn-secondary:contains('Mark Done')",run:"click",},{trigger:".o-mail-Message:contains('Play Mario Kart')",},],});return __exports;});;

/* /mail/static/tests/tours/mail_composer_autosave_tour.js */
odoo.define('@mail/../tests/tours/mail_composer_autosave_tour',['@web/core/registry','@web_tour/tour_utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_utils");registry.category("web_tour.tours").add("mail/static/tests/tours/mail_composer_autosave_tour.js",{steps:()=>[{content:"Edit the function field",trigger:".o_field_widget[name='function'] > .o_input",run:"edit Director",},{trigger:".o_form_sheet_bg",run:"click",},{content:"Click on Send Message",trigger:".o-mail-Chatter-sendMessage",run:"click",},{content:"Open the full composer",trigger:"[name='open-full-composer']",run:"click",},{content:"Edit the body",trigger:".o-wysiwyg div[contenteditable='true']",run:"editor Hello-- Mitchell Admin",},{content:"Click on Send Message",trigger:".o_mail_send[name='action_send_mail']",run:"click",},{content:"Check message is shown",trigger:'.o-mail-Message-body:contains("Hello")',},{trigger:".o_form_saved",},...stepUtils.toggleHomeMenu(),],});return __exports;});;

/* /mail/static/tests/tours/mail_composer_test_tour.js */
odoo.define('@mail/../tests/tours/mail_composer_test_tour',['@web/core/registry','@web/../tests/utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{contains,dragenterFiles,dropFiles,inputFiles}=require("@web/../tests/utils");registry.category("web_tour.tours").add("mail/static/tests/tours/mail_composer_test_tour.js",{steps:()=>[{content:"Wait for the chatter to be fully loaded",trigger:".o-mail-Chatter",async run(){await contains(".o-mail-Message",{count:1});},},{content:"Click on Send Message",trigger:"button:contains(Send message)",run:"click",},{content:"Write something in composer",trigger:".o-mail-Composer-input",run:"edit blahblah @Not && click body",},{content:"Mention a partner",trigger:".o-mail-Composer-suggestion:contains(Not A Demo User)",run:"click",},{content:"Add one file in composer",trigger:".o-mail-Composer button[title='Attach Files']",async run(){const files=[new File(["hello, world"],"file1.txt",{type:"text/plain"})];await inputFiles(".o-mail-Composer .o_input_file",files);},},{trigger:'.o-mail-AttachmentContainer:not(.o-isUploading):contains("file1.txt")',},{content:"Open full composer",trigger:"button[title='Open Full Composer']",run:"click",},{content:"Check composer keeps open after pushing Escape",trigger:".o_mail_composer_form_view",run:"press Escape",},{content:"Check the earlier provided attachment is listed",trigger:".o_field_mail_composer_attachment_list a:contains(file1.txt)",},{content:"Check subject is autofilled",trigger:'[name="subject"] input',run(){const subjectValue=document.querySelector('[name="subject"] input').value;if(subjectValue!=="Jane"){console.error(`Full composer should have "Jane" in subject input (actual: ${subjectValue})`);}},},{content:"Check composer content is kept and contains the user's signature",trigger:'.o_field_html[name="body"]',run(){const bodyContent=document.querySelector('.o_field_html[name="body"]').textContent;if(!bodyContent.includes("blahblah @Not A Demo User")){console.error(`Full composer should contain text from small composer ("blahblah @Not A Demo User") in body input (actual: ${bodyContent})`);}
const mentionLink=document.querySelector('.o_field_html[name="body"] a').textContent;if(!mentionLink.includes("@Not A Demo User")){console.error(`Full composer should contain mention link from small composer ("@Not A Demo User") in body input)`);}
if((bodyContent.match(/--\nErnest/g)||[]).length!==1){console.error("Full composer should contain the user's signature once.");}},},{content:"Trigger channel mention with #",trigger:".odoo-editor-editable",run(){this.anchor.dispatchEvent(new InputEvent("beforeinput",{inputType:"insertText",data:"#",bubbles:true,}));},},{content:"Search for general channel",trigger:".o-mail-MentionList input",run:"edit gen",},{content:"Select channel from suggestion",trigger:".o-mail-Composer-suggestion:contains(general)",run:"click",},{content:"Check channel mention is present in body",trigger:'.o_field_html[name="body"] .o_channel_redirect:contains(general)',},{content:"Drop a file on the full composer",trigger:".o_mail_composer_form_view",async run(){const files=[new File(["hi there"],"file2.txt",{type:"text/plain"})];await dragenterFiles(".o_mail_composer_form_view .o_form_renderer",files);await dropFiles(".o-Dropzone",files);},},{content:"Check the attachment is listed",trigger:".o_field_mail_composer_attachment_list a:contains(file2.txt)",},{content:"Click on the mail template selector",trigger:".mail-composer-template-dropdown-btn",run:"click",},{content:"Check a template is listed",trigger:'.mail-composer-template-dropdown.popover .o-dropdown-item:contains("Test template")',},{content:"Verify admin template is NOT listed",trigger:".mail-composer-template-dropdown.popover",run(){const hasAdminTemplate=[...document.querySelectorAll(".o-dropdown-item")].some((item)=>item.textContent.includes("Test template for admin"));if(hasAdminTemplate){console.error("Template assigned to the admin is visible to a non-assigned user! This should not happen.");}},},{content:"Send message from full composer",trigger:".o_mail_send",run:"click",},{content:"Check message is shown",trigger:'.o-mail-Message-body:contains("blahblah @Not A Demo User")',run:"click",},{content:"Click on envelope to see recipients of message",trigger:'.o-mail-Message:has(.o-mail-Message-body:contains("blahblah @Not A Demo User")) .o-mail-Message-notification',run:"click",},{content:"Check message has correct recipients",trigger:".o-mail-MessageNotificationPopover:contains('Not A Demo User (NotADemoUser@mail.com) Jane (jane@example.com) Mitchell Admin (test.admin@test.example.com)')",},{content:"Check message contains the first attachment",trigger:'.o-mail-Message .o-mail-AttachmentContainer:contains("file1.txt")',},{content:"Check message contains the second attachment",trigger:'.o-mail-Message .o-mail-AttachmentContainer:contains("file2.txt")',},{content:"Click on Send Message",trigger:"button:contains(Send message)",run:"click",},{content:"Open full composer",trigger:"button[title='Open Full Composer']",run:"click",},{content:"Check that the composer contains the signature",trigger:'.o_field_html[name="body"]',run(){const bodyContent=document.querySelector('.o_field_html[name="body"]').textContent;if((bodyContent.match(/--\nErnest/g)||[]).length!==1){console.log("Full composer should contain the user's signature once.");}},},{content:"Write something in full composer",trigger:".note-editable",run:"editor keep the content",},{content:"Close full composer",trigger:".btn-close",run:"click",},{content:"Click on Send Message",trigger:"button:contains(Send message)",run:"click",},{content:"Check full composer text is kept",trigger:".o-mail-Composer button[title='Open Full Composer'].active",run({queryFirst}){if(queryFirst(".o-mail-Composer-input").value!=="keep the content"){console.error("Composer in chatter should contain full composer text after discarding.");}},},{content:"Open full composer",trigger:"button[title='Open Full Composer']",run:"click",},{content:"Check that the composer doesn't add the user's signature twice",trigger:".note-editable",run(){const bodyContent=document.querySelector('.o_field_html[name="body"]').textContent;if((bodyContent.match(/--\nErnest/g)||[]).length!==0){console.error("The composer should not contain the user's signature.");}},},{content:"Close full composer",trigger:".btn-close",run:"click",},{content:"Click on Send Message",trigger:"button:contains(Send message)",run:"click",},{content:"Continue Message Composition with Small Composer",trigger:".o_popover:contains('Continue with Full Composer?') button:contains('No (Remove formatting)')",run:"click",},{content:"Send message from chatter",trigger:".o-mail-Composer-send:enabled",run:"click",},{content:"Check message is shown",trigger:'.o-mail-Message-body:contains("keep the content")',},{content:"Click on Send Message",trigger:"button:contains(Send message)",run:"click",},{content:"Write a message",trigger:".o-mail-Composer-input",run:"edit hello world",},{content:"Send message from chatter",trigger:".o-mail-Composer-send:enabled",run:"click",},{content:"Check message is shown",trigger:'.o-mail-Message-body:contains("hello world")',},],});return __exports;});;

/* /mail/static/tests/tours/mail_html_composer_test_tour.js */
odoo.define('@mail/../tests/tours/mail_html_composer_test_tour',['@web/core/registry','@web/../tests/utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{contains}=require("@web/../tests/utils");registry.category("web_tour.tours").add("mail/static/tests/tours/mail_html_composer_test_tour.js",{steps:()=>[{content:"Wait for the chatter to be fully loaded",trigger:".o-mail-Chatter",async run(){const composerService=odoo.__WOWL_DEBUG__.root.env.services["mail.composer"];composerService.setHtmlComposer();await contains(".o-mail-Message",{count:1});},},{content:"Click on Send Message",trigger:"button:contains(Send message)",run:"click",},{content:"Write something in composer",trigger:".o-mail-Composer-html.odoo-editor-editable",run:"editor Hello",},{content:"Select the text",trigger:".o-mail-Composer-html.odoo-editor-editable",run:"dblclick",},{trigger:".o-we-toolbar",},{content:"Bold the text",trigger:".o-we-toolbar button[title='Toggle bold']",run:"click",},{content:"The bolded text is in the composer",trigger:".o-mail-Composer-html.odoo-editor-editable strong:contains(Hello)",},{content:"Open full composer",trigger:"button[title='Open Full Composer']",run:"click",},{content:"Check composer keeps the formatted content",trigger:".o_mail_composer_message strong:contains(Hello)",},{content:"Focus the text in full composer",trigger:".o_mail_composer_message .odoo-editor-editable",run:"click",},{content:"Select the text in full composer",trigger:".o_mail_composer_message .odoo-editor-editable",run:"dblclick",},{trigger:".o-we-toolbar",},{content:"Remove the Bold",trigger:".o-we-toolbar button[title='Toggle bold']",run:"click",},{content:"Italicize the text",trigger:".o-we-toolbar button[title='Toggle italic']",run:"click",},{content:"The italicized text is in the full composer",trigger:".o_mail_composer_message em:contains(Hello)",},{content:"Close full composer",trigger:".btn-close",run:"click",},{content:"Click on Send Message",trigger:"button:not(.active):contains(Send message)",run:"click",},{content:"The italicized text is in the composer",trigger:".o-mail-Composer-html.odoo-editor-editable em:contains(Hello)",},],});return __exports;});;

/* /mail/static/tests/tours/mail_message_load_order_tour.js */
odoo.define('@mail/../tests/tours/mail_message_load_order_tour',['@web/core/registry','@web/../tests/utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{contains,scroll}=require("@web/../tests/utils");registry.category("web_tour.tours").add("mail_message_load_order_tour",{steps:()=>[{trigger:".o-mail-DiscussSidebarChannel:contains(MyTestChannel)",run:"click",},{trigger:".o-mail-Thread .o-mail-Message",async run(){await contains(".o-mail-Thread .o-mail-Message",{count:30});await contains(".o-mail-Thread",{scroll:"bottom"});},},{trigger:"*[title='Pinned Messages']",run:"click",},{content:"Click on invisible jump (should hover card to be visible)",trigger:".o-mail-MessageCard-jump:not(:visible)",run:"click",},{trigger:".o-mail-Thread .o-mail-Message:first .o-mail-Message-textContent:not(:contains(31))",async run(){await contains(".o-mail-Thread .o-mail-Message",{count:31});await contains(".o-mail-Thread",{scroll:0});const messages=Array.from(document.querySelectorAll(".o-mail-Thread .o-mail-Message-content")).map((el)=>el.innerText);for(let i=0;i<31;i++){if(messages[i]!==(i+1).toString()){throw new Error("Wrong message order after loading around");}}
await scroll(".o-mail-Thread","bottom");},},{trigger:".o-mail-Thread .o-mail-Message .o-mail-Message-textContent:contains(17)",async run(){await contains(".o-mail-Thread .o-mail-Message",{count:60});const messages=Array.from(document.querySelectorAll(".o-mail-Thread .o-mail-Message-content")).map((el)=>el.innerText);for(let i=0;i<60;i++){if(messages[i]!==(i+1).toString()){throw new Error("Wrong message order after loading after");}}},},],});return __exports;});;

/* /mail/static/tests/tours/mail_template_dynamic_placeholder_tour.js */
odoo.define('@mail/../tests/tours/mail_template_dynamic_placeholder_tour',['@web/core/registry','@web_tour/tour_utils','@web/core/utils/concurrency'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_utils");const{delay}=require("@web/core/utils/concurrency");registry.category("web_tour.tours").add("mail_template_dynamic_placeholder_tour",{url:"/odoo",steps:()=>[stepUtils.showAppsMenuItem(),{content:'Go into the Setting "app"',trigger:'.o_app[data-menu-xmlid="base.menu_administration"]',run:"click",},{content:"Open email templates",trigger:'button[name="open_mail_templates"]',run:"click",},{content:"Create a new email template",trigger:"button.o_list_button_add",run:"click",},{content:'Insert # inside "Subject" input',trigger:'div[name="subject"] input[type="text"]',run:"edit(no_model_id #)",},{content:'Select "Contact" model',trigger:'div[name="model_id"] input[type="text"]',run:"edit Contact",},{content:"Wait for the autocomplete RPC",trigger:'div[name="model_id"] .ui-autocomplete:contains("Contact")',run:async()=>{await delay(300);},},{content:"Click on contact",trigger:'div[name="model_id"] .ui-autocomplete',run:async function(){const contact=Array.from(document.querySelectorAll('div[name="model_id"] .ui-autocomplete .dropdown-item')).find((el)=>el.textContent==="Contact");await contact.click();},},{content:"Wait for the drop down to disappear",trigger:'div[name="model_id"] .o-autocomplete:not(:has(.ui-autocomplete))',run:async()=>{await delay(200);},},{content:'Retry insert # inside "Subject" input',trigger:'div[name="subject"] input[type="text"]',run:"edit (yes_model_id) && press #",},{content:"Check if the dynamic placeholder popover is opened",trigger:"div.o_model_field_selector_popover",},{content:"filter the dph result",trigger:"div.o_model_field_selector_popover_search input[type='text']",run:"edit name",},{content:"Click on the first entry of the dynamic placeholder",trigger:'div.o_model_field_selector_popover button:contains("Company Name")',run:"click",},{content:"Enter a default value",trigger:'div.o_model_field_selector_popover .o_model_field_selector_default_value_input input[type="text"]',run:"edit defValue",},{content:"Click on the insert button",trigger:"div.o_model_field_selector_popover button:first-child",run:"click",},{content:"Wait for the popover to disappear",trigger:"body:not(:has(.o_model_field_selector_popover))",run:"click",},{content:"Check if subject value was correctly updated",trigger:'div[name="subject"] input[type="text"]',run(){const subjectValue=this.anchor.value;const correctValue="yes_model_id {{object.company_name|||defValue}}";if(subjectValue!==correctValue){console.error(`Email template should have "${correctValue}" in subject input (actual: ${subjectValue})`);}},},{content:"Insert text inside editable",trigger:".note-editable.odoo-editor-editable",async run(actions){await actions.editor(`/`);document.querySelector(".note-editable").dispatchEvent(new InputEvent("input",{inputType:"insertText",data:"/",}));},},{content:"Click on the the dynamic placeholder powerBox options",trigger:"div.o-we-powerbox .o-we-command:contains(Dynamic Placeholder)",run:"click",},{content:"Check if the dynamic placeholder popover is opened",trigger:"div.o_model_field_selector_popover",run:"click",},{content:"filter the dph result",trigger:"div.o_model_field_selector_popover_search input[type='text']",run:"edit name",},{content:"Click on the first entry of the dynamic placeholder",trigger:'div.o_model_field_selector_popover button:contains("Company Name")',run:"click",},{content:"Enter a default value",trigger:'div.o_model_field_selector_popover .o_model_field_selector_default_value_input input[type="text"]',run:"edit defValue",},{content:"Click on the insert button",trigger:"div.o_model_field_selector_popover button:first-child",run:"click",},{content:"Ensure the editable contain the dynamic placeholder t tag",trigger:`.note-editable.odoo-editor-editable t[t-out="object.company_name"]:contains("defValue")`,},{content:'Type "Push Notification Device" model',trigger:'div[name="model_id"] input[type="text"]',run:"edit Push Notification Device",},{content:'Select "Push Notification Device" model',trigger:'a.dropdown-item:contains("Push Notification Device")',run:"click",},{content:"Insert text inside editable",trigger:".note-editable.odoo-editor-editable",async run(actions){await actions.editor(`/`);document.querySelector(".note-editable").dispatchEvent(new InputEvent("input",{inputType:"insertText",data:"/",}));},},{content:"Click on the the dynamic placeholder powerBox options",trigger:"div.o-we-powerbox .o-we-command:contains(Dynamic Placeholder)",run:"click",},{content:"Check if the dynamic placeholder popover is opened",trigger:"div.o_model_field_selector_popover",run:"click",},{content:"filter the dph result",trigger:"div.o_model_field_selector_popover_search input[type='text']",run:"edit created on",},{content:"Click on the first entry of the dynamic placeholder",trigger:'div.o_model_field_selector_popover li:first-child button:contains("Created on")',run:"click",},{content:"Enter a default value",trigger:"div.o_model_field_selector_popover .o_model_field_selector_default_value_input input[type='text']",run:"edit localTime",},{content:"Click on the insert button",trigger:"div.o_model_field_selector_popover button:first-child:contains('Insert)",run:"click",},{content:"Ensure the editable contain the dynamic placeholder t tag",trigger:`.note-editable.odoo-editor-editable t[t-out="format_datetime(object.create_date, tz=object.partner_id.tz) or 'localTime'"]:contains("localTime")`,},{content:"Discard form changes",trigger:"button.o_form_button_cancel",run:"click",},{content:"Wait for the form view to disappear",trigger:"body:not(:has(.o_form_sheet))",},],});return __exports;});;

/* /mail/static/tests/tours/user_modify_own_profile_tour.js */
odoo.define('@mail/../tests/tours/user_modify_own_profile_tour',['@web/core/registry','@web/../tests/utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{click,contains}=require("@web/../tests/utils");registry.category("web_tour.tours").add("mail/static/tests/tours/user_modify_own_profile_tour.js",{steps:()=>[{content:"Open user account menu",trigger:".o_user_menu button",run:"click",},{content:"Open preferences / profile screen",trigger:"[data-menu=preferences]",run:"click",},{content:"Update the notification type",trigger:'.modal div[name="notification_type"] input[data-value="inbox"]',async run(){await click('.modal div[name="notification_type"] input[data-value="inbox"]');await contains(".o_form_dirty",{count:1});},},{content:"Save the form",trigger:'button[name="preference_save"]',run:"click",},{content:"Wait until the modal is closed",trigger:"body:not(.modal-open)",async run(){await contains(".o_form_dirty",{count:0});},},],});return __exports;});;

/* /auth_passkey/static/tests/passkeys_delete.js */
odoo.define('@auth_passkey/../tests/passkeys_delete',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add('passkeys_tour_delete',{url:'/odoo',steps:()=>[{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open preferences / profile screen",trigger:'[data-menu=preferences]',run:'click',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Ensure there is only one passkey",trigger:'button:contains("Add Passkey")',run:()=>{let amount=document.querySelectorAll("div[name='auth_passkey_key_ids'] article").length;if(amount!=1){throw Error("Amount of Passkeys must be 1");}},},{content:"Open Passkey dropdown",trigger:'[name="auth_passkey_key_ids"] .o_dropdown_kanban .o-dropdown:not(:visible)',run:'click',},{content:"Delete Passkey",trigger:'a[name="action_delete_passkey"]',run:'click',},{content:"Identitycheck: use password",trigger:'button[name="action_use_password"]',run:'click',},{content:"Check that we have to enter enhanced security mode",trigger:".modal div:contains(Enter your current password)",},{content:"Input password",trigger:'.modal [name=password] input',run:"edit admin",},{content:"Confirm",trigger:".modal button:contains(Confirm Password)",run:"click",},{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open preferences / profile screen",trigger:'[data-menu=preferences]',run:'click',},{content:"Make sure the Preferences tab is open",trigger:'label:contains("Email Signature")',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Ensure there are no more passkeys",trigger:'button:contains("Add Passkey")',run:()=>{let amount=document.querySelectorAll("div[name='auth_passkey_key_ids'] article").length;if(amount!=0){throw Error("Amount of Passkeys must be 0");}},}]})
return __exports;});;

/* /auth_passkey/static/tests/passkeys_login.js */
odoo.define('@auth_passkey/../tests/passkeys_login',['@web/core/registry','@web/core/utils/patch','@auth_passkey/../lib/simplewebauthn'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{patch}=require("@web/core/utils/patch");const passkeyLib=require("@auth_passkey/../lib/simplewebauthn");registry.category("web_tour.tours").add('passkeys_tour_login',{url:'/web/login',steps:()=>[{content:"Inject authenticator data",trigger:'body',run:()=>{patch(passkeyLib,{async startAuthentication(){return{"id":"y6aJVJsvvSSkbwTeGZ1FbQP_jCDho7EBPwZq-3lAjQ0","rawId":"y6aJVJsvvSSkbwTeGZ1FbQP_jCDho7EBPwZq-3lAjQ0","response":{"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAA","clientDataJSON":"eyJjaGFsbGVuZ2UiOiJMTnBWMGRQSU10bXBTd0dlbklIX2gxVnljUXVBZ0ZnUVJKOVRQS0JvTmF5U2NOQUVyUy1yc25hVTE5bjdfQWFYemVpWVJnM25HSTN5dUgwYWk2VVBYQSIsImNyb3NzT3JpZ2luIjpmYWxzZSwib3JpZ2luIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6ODg4OCIsInR5cGUiOiJ3ZWJhdXRobi5nZXQifQ","signature":"MEYCIQCqkh2NBQQao5uDTaBKyNhiEpnk4jgbH-PjdLAul9-d0gIhAMObtNTbaEMUILdNgCT01BKNN4NHRzkzsGaDN2Ozu0WX","userHandle":"Ng",},"type":"public-key","clientExtensionResults":{},"authenticatorAttachment":"platform",};},});},},{content:'Login with Passkey',trigger:'a:contains("Use a Passkey")',run:'click',expectUnloadPage:true,},{content:'Check if we are logged in',trigger:'.o_user_menu .dropdown-toggle',},]})
return __exports;});;

/* /auth_passkey/static/tests/passkeys_registration.js */
odoo.define('@auth_passkey/../tests/passkeys_registration',['@web/core/registry','@web/core/utils/patch','@auth_passkey/../lib/simplewebauthn'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{patch}=require("@web/core/utils/patch");const passkeyLib=require("@auth_passkey/../lib/simplewebauthn");let unpatchPasskeyRegistration;registry.category("web_tour.tours").add('passkeys_tour_registration',{url:'/odoo',steps:()=>[{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open preferences / profile screen",trigger:'[data-menu=preferences]',run:'click',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Ensure there are no passkeys already",trigger:'button:contains("Add Passkey")',run:()=>{let amount=document.querySelectorAll("div[name='auth_passkey_key_ids'] article").length;if(amount!=0){throw Error("Amount of Passkeys must be 0");}},},{content:"Add a Passkey",trigger:'button:contains("Add Passkey")',run:'click',},{content:"Check that we have to enter enhanced security mode",trigger:".modal div:contains(Enter your current password)",},{content:"Input password",trigger:'.modal [name=password] input',run:"edit admin",},{content:"Confirm",trigger:".modal button:contains(Confirm Password)",run:"click",},{content:"Ready to create Passkey",trigger:".modal div:contains(Create Passkey)",},{content:"Input passkey name",trigger:'.modal .o_field_char input',run:"edit test_passkey_one",},{content:"Override startRegistration",trigger:'body',run:()=>{unpatchPasskeyRegistration=patch(passkeyLib,{async startRegistration(){return{"id":"L2p6jvcWuCMTRmkZHKqqvQbz0Dhk3JbJOx1F8ci99nSNjlfx3Z7nkigMdUACLggB","rawId":"L2p6jvcWuCMTRmkZHKqqvQbz0Dhk3JbJOx1F8ci99nSNjlfx3Z7nkigMdUACLggB","response":{"attestationObject":"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjCSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2PFAAAAAgAAAAAAAAAAAAAAAAAAAAAAMC9qeo73FrgjE0ZpGRyqqr0G89A4ZNyWyTsdRfHIvfZ0jY5X8d2e55IoDHVAAi4IAaUBAgMmIAEhWCAvanqO9xa4IxNGaRkcMSyBudC-JDZYY9gyMqknP2IkUiJYINqumy9viKCeo_xpFU3XzyssfEReXvMM1_fmZN-wMpDPoWtjcmVkUHJvdGVjdAI","clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiVW9hNk01akVQN0kzVG95SzlRQTB2ZjhJY3NlemZlSmswcmdzMXBMVVdyTWdGOXZkMC03RHY1aVYzeFc3cjcwLVlxa3dlUlhoQUNtRFBtaEhLdEFJZVEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgwNjkiLCJjcm9zc09yaWdpbiI6ZmFsc2V9","transports":["nfc","usb",],"publicKeyAlgorithm":-7,"publicKey":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL2p6jvcWuCMTRmkZHDEsgbnQviQ2WGPYMjKpJz9iJFLarpsvb4ignqP8aRVN188rLHxEXl7zDNf35mTfsDKQzw","authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2PFAAAAAgAAAAAAAAAAAAAAAAAAAAAAMC9qeo73FrgjE0ZpGRyqqr0G89A4ZNyWyTsdRfHIvfZ0jY5X8d2e55IoDHVAAi4IAaUBAgMmIAEhWCAvanqO9xa4IxNGaRkcMSyBudC-JDZYY9gyMqknP2IkUiJYINqumy9viKCeo_xpFU3XzyssfEReXvMM1_fmZN-wMpDPoWtjcmVkUHJvdGVjdAI",},"type":"public-key","clientExtensionResults":{},"authenticatorAttachment":"cross-platform",};},});},},{content:"Click the Create button",trigger:".modal button:contains(Create)",run:"click",},{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Return startRegistration to original state",trigger:'body',run:()=>{unpatchPasskeyRegistration();},},{content:"Open preferences / profile screen",trigger:'[data-menu=preferences]',run:'click',},{content:"Make sure the Preferences tab is open",trigger:'label:contains("Email Signature")',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Ensure there is one passkey",trigger:'button:contains("Add Passkey")',run:()=>{let amount=document.querySelectorAll("div[name='auth_passkey_key_ids'] article").length;if(amount!=1){throw Error("Amount of Passkeys must be 1");}},},]})
return __exports;});;

/* /auth_passkey/static/tests/passkeys_verify.js */
odoo.define('@auth_passkey/../tests/passkeys_verify',['@web/core/registry','@web/core/utils/patch','@auth_passkey/../lib/simplewebauthn'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{patch}=require("@web/core/utils/patch");const passkeyLib=require("@auth_passkey/../lib/simplewebauthn");let unpatchPasskeyVerify;registry.category("web_tour.tours").add('passkeys_tour_verify',{url:'/odoo',steps:()=>[{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open preferences / profile screen",trigger:'[data-menu=preferences]',run:'click',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Ensure there is one passkey",trigger:'button:contains("Add Passkey")',run:()=>{let amount=document.querySelectorAll("div[name='auth_passkey_key_ids'] article").length;if(amount!=1){throw Error("Amount of Passkeys must be 1");}},},{content:"Trigger security prompt",trigger:'button:contains("Add Passkey")',run:'click',},{content:"Override startAuthentication",trigger:'body',run:()=>{unpatchPasskeyVerify=patch(passkeyLib,{async startAuthentication(){return{"id":"L2p6jvcWuCMTRmkZHKqqvQbz0Dhk3JbJOx1F8ci99nSNjlfx3Z7nkigMdUACLggB","rawId":"L2p6jvcWuCMTRmkZHKqqvQbz0Dhk3JbJOx1F8ci99nSNjlfx3Z7nkigMdUACLggB","response":{"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAAAw","clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiREtydzVJZUZpTDB3X3k1b0IwUkFUUHJxRzFlRk9DMlA3eUVpWENzdEJSdVpZYlNCQmtBV2ZoQUlJbmtNcVdqWUlOOHZiS243SjNQTVhfVGh6bkhwcWciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgwNjkiLCJjcm9zc09yaWdpbiI6ZmFsc2V9","signature":"MEUCIQD5iaPp48QMS3amx4PS89kv_EBAo3bBkaWnLzWlSgFSXgIgLWKEv9xR_ZwVXZbw2zx459RKbrQuAcd-UqD4gJw1lWY","userHandle":"Mg",},"type":"public-key","clientExtensionResults":{},"authenticatorAttachment":"cross-platform",};},});},},{content:"Click Use Passkey",trigger:'button:contains("Use Passkey")',run:'click',},{content:"Ready to create Passkey",trigger:".modal div:contains(Create Passkey)",},{content:"Return startAuthentication to original state",trigger:'body',run:()=>{unpatchPasskeyVerify();},}]})
return __exports;});;

/* /auth_totp/static/tests/apikeys_flow.js */
odoo.define('@auth_totp/../tests/apikeys_flow',['@web/core/network/rpc','@web/core/registry'],function(require){'use strict';let __exports={};const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const openUserPreferenceSecurity=()=>[{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open preferences / profile screen",trigger:'[data-menu=preferences]',run:'click',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',}]
registry.category("web_tour.tours").add('apikeys_tour_setup',{url:'/odoo?debug=1',steps:()=>[...openUserPreferenceSecurity(),{content:"Open API keys wizard",trigger:'button:contains("Add API Key")',run:"click",},{content:"Check that we have to enter enhanced security mode",trigger:".modal div:contains(Enter your current password)",},{content:"Input password",trigger:'.modal [name=password] input',run:"edit test_user",},{content:"Confirm",trigger:".modal button:contains(Confirm Password)",run:"click",},{content:"Check that we're now on the key description dialog",trigger:'.modal p:contains("Enter a description of and purpose for the key.")',},{content:"Enter description",trigger:'.modal [name=name] input',run:"edit my key",},{content:"Confirm key creation",trigger:'.modal button:contains("Generate key")',run:"click",},{content:"Check that we're on the last step & grab key",trigger:'.modal p:contains("Here is your new API key")',run:async()=>{const key=document.querySelector("code [name=key] span").textContent;await rpc('/web/dataset/call_kw',{model:'ir.logging',method:'send_key',args:[key],kwargs:{},});}},{trigger:"button:contains(Done)",run:"click",},...openUserPreferenceSecurity(),{content:"check that our key is present",trigger:'[name=api_key_ids] .o_kanban_record:contains("my key")',}]});registry.category("web_tour.tours").add('apikeys_tour_teardown',{url:'/odoo?debug=1',steps:()=>[{content:'Open preferences',trigger:'.o_user_menu .dropdown-toggle',run:"click",},{trigger:'[data-menu=preferences]',run:"click",},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Open kanban dropdown menu of the key",trigger:'[name=api_key_ids] .o_kanban_record:contains("my key") .oe_kanban_action[name="remove"]',run:'click',},{content:"Input password for security mode again",trigger:".modal [name=password] input",run:"edit test_user",},{content:"And confirm",trigger:".modal button:contains(Confirm Password)",run:"click",},{trigger:"body:not(:has(.modal))",},{content:'Re-open preferences again',trigger:'.o_user_menu .dropdown-toggle',run:"click",},{trigger:'[data-menu=preferences]',run:"click",},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',},{content:"Check that there's no more keys",trigger:"body:not(:has(.o_notebook [name=api_key_ids]))",}]});return __exports;});;

/* /auth_totp/static/tests/totp_flow.js */
odoo.define('@auth_totp/../tests/totp_flow',['@bus/workers/websocket_worker','@web/core/network/rpc','@web/core/registry','@web_tour/tour_utils','@odoo/owl'],function(require){'use strict';let __exports={};const{WORKER_STATE}=require("@bus/workers/websocket_worker");const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_utils");const{whenReady}=require("@odoo/owl");function openRoot(){return[{content:"return to client root to avoid race condition",trigger:'body',run(){document.querySelector("body").classList.add("wait");window.location='/odoo';},expectUnloadPage:true,},{content:"wait for client reload",trigger:'body:not(.wait)',}];}
function openUserPreferencesAtSecurityTab(){return[{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open My Preferences",trigger:'[data-menu=preferences]',run:'click',},{content:"wait for security tab",trigger:'a[role=tab]:contains("Security")',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Security")',run:'click',}];}
function closePreferencesDialog({content,totp_state}){let trigger;switch(totp_state){case true:trigger='button[name=action_totp_disable]';break;case false:trigger='button[name=action_totp_enable_wizard]';break;case undefined:trigger='div:contains("Two-factor Authentication") + button';break;default:throw new Error(`Invalid totp state ${totp_state}`)}
return[{content,trigger:'a[role=tab]:contains("Security").active',},{trigger,async run(helpers){const modal=document.querySelector(".o_dialog");if(modal){modal.querySelector("button[name=preference_cancel]").click();}}},{trigger:'body:not(:has(.o_dialog))',}];}
registry.category("web_tour.tours").add('totp_tour_setup',{url:'/odoo',steps:()=>[...openUserPreferencesAtSecurityTab(),{content:"Open totp wizard",trigger:'a[role=tab]:contains("Security").active',},{trigger:"button[name=action_totp_enable_wizard]",run:"click",},{trigger:".modal div:contains(Enter your current password)",},{content:"Check that we have to enter enhanced security mode and input password",trigger:'[name=password] input',run:'edit test_user',},{content:"Confirm",trigger:"button:contains(Confirm Password)",run:"click",},{content:"Check the wizard has opened",trigger:'.modal:contains("Two-Factor Authentication Activation")',},{content:"Get secret from collapsed div",trigger:`.modal a:contains("Cannot scan it?")`,async run(helpers){const secret=this.anchor.closest("div").querySelector("[name=secret] span:first-child");const copyBtn=secret.querySelector("button");if(copyBtn){copyBtn.remove();}
const token=await rpc('/totphook',{secret:secret.textContent,offset:0,});await helpers.edit(token,'[name=code] input');}},{trigger:".modal button.btn-primary:contains(Enable Two-Factor Authentication)",run:"click",},{trigger:".o_notification_content:contains(2-Factor authentication is now enabled)",},...openRoot(),...openUserPreferencesAtSecurityTab(),...closePreferencesDialog({content:"Check that the button has changed",totp_state:true,}),]});registry.category("web_tour.tours").add('totp_login_enabled',{url:'/',steps:()=>[{content:"check that we're on the login page or go to it",isActive:["body:not(:has(input#login))"],trigger:"a:contains(Sign in)",run:"click",expectUnloadPage:true,},{content:"input login",trigger:'input#login',run:"edit test_user",},{content:'input password',trigger:'input#password',run:"edit test_user",},{content:"click da button",trigger:'button:contains("Log in")',run:"click",expectUnloadPage:true,},{content:"expect totp screen",trigger:'label:contains(Authentication Code)',run:"click",},{content:"input incorrect code",trigger:'input[name=totp_token]',async run(helpers){await rpc("/totphook",{offset:-2});helpers.edit("123456");}},{trigger:`button:contains("Log in")`,run:"click",expectUnloadPage:true,},{content:"using an incorrect token should fail",trigger:"p.alert.alert-danger:contains(Verification failed, please double-check the 6-digit code)",},{content:"reuse same code",trigger:'input[name=totp_token]',async run(helpers){const token=await rpc("/totphook",{offset:0});helpers.edit(token);}},{trigger:`button:contains("Log in")`,run:"click",expectUnloadPage:true,},{content:"reusing the same token should fail",trigger:"p.alert.alert-danger:contains(Verification failed, please use the latest 6-digit code)",},{content:"input code",trigger:'input[name=totp_token]',async run(helpers){const token=await rpc('/totphook',{offset:1});helpers.edit(token);}},{trigger:`button:contains("Log in")`,run:"click",expectUnloadPage:true,},{content:"check we're logged in",trigger:".o_user_menu .dropdown-toggle",}]});registry.category("web_tour.tours").add('totp_login_device',{url:'/',steps:()=>[{content:"check that we're on the login page or go to it",isActive:["body:not(:has(input#login))"],trigger:"a:contains(Sign in)",run:"click",expectUnloadPage:true,},{content:"input login",trigger:'input#login',run:"edit test_user",},{content:'input password',trigger:'input#password',run:"edit test_user",},{content:"click da button",trigger:'button:contains("Log in")',run:"click",expectUnloadPage:true,},{content:"expect totp screen",trigger:'label:contains(Authentication Code)',run:"click",},{content:"check remember device box",trigger:'label[for=switch-remember]',run:"click",},{content:"input code",trigger:'input[name=totp_token]',async run(helpers){const token=await rpc('/totphook',{offset:2});helpers.edit(token);}},{trigger:"button:contains(Log in)",run:"click",expectUnloadPage:true,},{trigger:".o_web_client .o_navbar",async run(){await whenReady();}},{trigger:".o_web_client .o_navbar",async run(){await new Promise((resolve)=>{const bus=odoo.__WOWL_DEBUG__.root.env.services.bus_service;bus.addEventListener("BUS:CONNECT",resolve,{once:true});if(bus.workerState===WORKER_STATE.CONNECTED){resolve();}});},},{content:"check we're logged in",trigger:".o_user_menu .dropdown-toggle",run:'click',},{content:"click the Log out button",trigger:'.dropdown-item[data-menu=logout]',run:"click",expectUnloadPage:true,},{content:"check that we're back on the login page or go to it",trigger:'input#login, a:contains(Log in)',run:"edit Test",},{content:"input login again",trigger:'input#login',run:"edit test_user",},{content:'input password again',trigger:'input#password',run:"edit test_user",},{content:"click da button again",trigger:'button:contains("Log in")',run:"click",expectUnloadPage:true,},{content:"check we're logged in without 2FA",trigger:".o_user_menu .dropdown-toggle",},...openUserPreferencesAtSecurityTab(),{content:"Open totp wizard",trigger:'a[role=tab]:contains("Security").active',},{trigger:"button[name=action_totp_disable]",run:"click",},{trigger:".modal div:contains(Enter your current password)",},{content:"Check that we have to enter enhanced security mode and input password",trigger:'.modal [name=password] input',run:"edit test_user",},{content:"Confirm",trigger:".modal button:contains(Confirm Password)",run:"click",},{trigger:".o_notification_content:contains(Two-factor authentication disabled)",},...openRoot(),...openUserPreferencesAtSecurityTab(),...closePreferencesDialog({content:"Check that the button has changed",totp_state:false}),]});registry.category("web_tour.tours").add('totp_login_disabled',{url:'/',steps:()=>[{content:"check that we're on the login page or go to it",isActive:["body:not(:has(input#login))"],trigger:"a:contains(Sign in)",run:"click",expectUnloadPage:true,},{content:"input login",trigger:'input#login',run:"edit test_user",},{content:'input password',trigger:'input#password',run:"edit test_user",},{content:"click da button",trigger:'button:contains("Log in")',run:"click",expectUnloadPage:true,},...openUserPreferencesAtSecurityTab(),...closePreferencesDialog({})]});registry.category("web_tour.tours").add('totp_admin_disables',{url:'/odoo',steps:()=>[stepUtils.showAppsMenuItem(),{content:'Go to settings',trigger:'[data-menu-xmlid="base.menu_administration"]',run:"click",},{content:'Wait for page',trigger:'.o_menu_brand:contains("Settings")',},{content:"Open Users menu",trigger:'[data-menu-xmlid="base.menu_users"]',run:"click",},{content:"Open Users view",trigger:'[data-menu-xmlid="base.menu_action_res_users"]',run:"click",},{content:"Find test_user User",trigger:'tr:has(td.o_data_cell:contains("test_user")) '+'.o_list_record_selector input[type=checkbox]',run:"click",},{content:"Open Actions menu",trigger:'button.dropdown-toggle:contains("Action")',run:"click",},{content:"Select totp remover",trigger:'span.dropdown-item:contains(Disable two-factor authentication)',run:"click",},{trigger:".modal div:contains(Enter your current password)",},{content:"Check that we have to enter enhanced security mode & input password",trigger:'.modal [name=password] input',run:"edit admin",},{content:"Confirm",trigger:".modal button:contains(Confirm Password)",run:"click",},{content:"Wait for user to be unchecked (~ action done)",trigger:'tr:has(td.o_data_cell:contains(test_user)) '+'.o_list_record_selector input[type=checkbox]:not(:checked)',},{content:"open the user's form",trigger:"td.o_data_cell:contains(test_user)",run:"click",},{content:"wait for Security Tab to appear",trigger:"a.nav-link:contains(Security)",},{content:"go to Security Tab",trigger:"a.nav-link:contains(Security)",run:"click",},{content:"check 2FA button: should be disabled",trigger:'body:not(:has(button[name=action_totp_enable_wizard]))',}]})
return __exports;});;

/* /auth_totp_mail/static/tests/totp_flow.js */
odoo.define('@auth_totp_mail/../tests/totp_flow',['@web/core/registry','@web_tour/tour_utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_utils");function openAccountSettingsTab(){return[{content:'Go to settings',trigger:'[data-menu-xmlid="base.menu_administration"]',run:"click",},{content:'Wait for page',trigger:'.o_menu_brand:contains("Settings")',},{content:"Open Users menu",trigger:'[data-menu-xmlid="base.menu_users"]',run:"click",},{content:"Open Users view",trigger:'[data-menu-xmlid="base.menu_action_res_users"]',run:function(helpers){const breadcrumb=document.querySelector('.breadcrumb');if(!breadcrumb||!breadcrumb.textContent.includes("Users")){helpers.click();}else{helpers.click('[data-menu-xmlid="base.menu_users"]');}}}];}
registry.category("web_tour.tours").add('totp_admin_self_invite',{url:'/odoo',steps:()=>[stepUtils.showAppsMenuItem(),...openAccountSettingsTab(),{content:"open the user's form",trigger:"td.o_data_cell:contains(admin)",run:"click",},{content:"go to Security Tab",trigger:"a.nav-link:contains(Security)",run:"click",},{content:"check that user cannot invite themselves to use 2FA.",trigger:"body:not(:has(button:contains(Invite to use 2FA)))",}]});registry.category("web_tour.tours").add('totp_admin_invite',{url:'/odoo',steps:()=>[stepUtils.showAppsMenuItem(),...openAccountSettingsTab(),{content:"open the user's form",trigger:"td.o_data_cell:contains(test_user)",run:"click",},{content:"go to security Tab",trigger:"a.nav-link:contains(Security)",run:"click",},{content:"check that test_user user can be invited to use 2FA.",trigger:"button:contains(Invite to use 2FA)",}]});return __exports;});;

/* /web_enterprise/static/tests/tours/web_enterprise_tours.js */
odoo.define('@web_enterprise/../tests/tours/web_enterprise_tours',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("web_enterprise.test_studio_list_upsell",{steps:()=>[{trigger:".o_list_view",},{trigger:".o_optional_columns_dropdown > button",run:"click",},{trigger:" .o-dropdown--menu .dropdown-item-studio",},],});registry.category("web_tour.tours").add("web_enterprise.test_studio_no_list_upsell_if_blacklisted",{steps:()=>[{trigger:".o_list_view",},{trigger:".o_optional_columns_dropdown > button",run:"click",},{trigger:".o-dropdown--menu:not(:has(.dropdown-item-studio))",},],});return __exports;});;

/* /mail_enterprise/static/tests/tours/discuss_channel_expand_test_tour.js */
odoo.define('@mail_enterprise/../tests/tours/discuss_channel_expand_test_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");registry.category("web_tour.tours").add("mail_enterprise/static/tests/tours/discuss_channel_expand_test_tour.js",{url:"/odoo",steps:()=>[{trigger:".o-mail-DiscussSystray-class .fa-comments",run:"click",},{trigger:".o-mail-NotificationItem:contains('test-mail-channel-expand-tour')",run:"click",},{trigger:'.o-mail-ChatWindow:contains("test-mail-channel-expand-tour") [title="Open Actions Menu"]',run:"click",},{trigger:'.o-dropdown-item:contains("Open in Discuss")',run:"click",},{content:"Check that first message of #test-mail-channel-expand-tour is shown in Discuss app",trigger:'.o-mail-DiscussContent .o-mail-Message-body:contains("test-message-mail-channel-expand-tour")',},],});return __exports;});;

/* /web/static/tests/legacy/ignore_missing_deps_stop.js */
window.__odooIgnoreMissingDependencies=false;