
/* /base/static/tests/test_ir_model_fields_translation.js */
odoo.define('@base/../tests/test_ir_model_fields_translation',['@web/core/registry','@web_tour/tour_service/tour_utils'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_service/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','@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{_t}=require("@web/core/l10n/translation");const{registerCleanup}=require("@web/../tests/legacy/helpers/cleanup");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,};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/user_switch_tour.js */
odoo.define('@web/../tests/tours/user_switch_tour',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");function logout(){return[{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,},];}
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;});;

/* /auth_totp/static/tests/totp_flow.js */
odoo.define('@auth_totp/../tests/totp_flow',['@odoo/hoot-dom','@web/core/network/rpc','@web/core/registry','@web_tour/tour_service/tour_utils'],function(require){'use strict';let __exports={};const{waitFor}=require("@odoo/hoot-dom");const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const{stepUtils}=require("@web_tour/tour_service/tour_utils");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 openUserProfileAtSecurityTab(){return[{content:'Open user account menu',trigger:'.o_user_menu .dropdown-toggle',run:'click',},{content:"Open preferences / profile screen",trigger:'[data-menu=settings]',run:'click',},{content:"Switch to security tab",trigger:'a[role=tab]:contains("Account Security")',run:'click',}];}
function closeProfileDialog({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='button.o_auth_2fa_btn';break;default:throw new Error(`Invalid totp state ${totp_state}`)}
return[{content,trigger:'a[role=tab]:contains("Account Security").active',async run(helpers){await waitFor(trigger,{timeout:5000});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:()=>[...openUserProfileAtSecurityTab(),{content:"Open totp wizard",trigger:'button[name=action_totp_enable_wizard]',run:"click",},{trigger:".modal div:contains(entering your 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 li:contains("When requested to do so")',},{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});await helpers.edit(token,'[name=code] input');}},{trigger:".modal button.btn-primary:contains(Activate)",run:"click",},{trigger:".o_notification_content:contains(2-Factor authentication is now enabled)",},...openRoot(),...openUserProfileAtSecurityTab(),...closeProfileDialog({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 code",trigger:'input[name=totp_token]',async run(helpers){const token=await rpc('/totphook');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')
helpers.edit(token);}},{trigger:"button:contains(Log in)",run:"click",expectUnloadPage:true,},{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",},...openUserProfileAtSecurityTab(),{content:"Open totp wizard",trigger:'a[role=tab]:contains("Account Security").active',},{trigger:"button[name=action_totp_disable]",run:"click",},{trigger:".modal div:contains(entering your 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(),...openUserProfileAtSecurityTab(),...closeProfileDialog({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,},...openUserProfileAtSecurityTab(),...closeProfileDialog({})]});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(entering your 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:"go to Account security Tab",trigger:"a.nav-link:contains(Account Security)",run:"click",},{content:"check 2FA button: should be disabled",trigger:'button[name=action_totp_enable_wizard]:disabled',}]})
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",},],});return __exports;});