UNPKG

@clerk/testing

Version:

Utilities to help you create E2E test suites for apps using Clerk

2 lines • 20.3 kB
"use strict";var P=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var te=Object.getOwnPropertyNames;var re=Object.prototype.hasOwnProperty;var ae=(a,e)=>{for(var r in e)P(a,r,{get:e[r],enumerable:!0})},oe=(a,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of te(e))!re.call(a,o)&&o!==r&&P(a,o,{get:()=>e[o],enumerable:!(t=ee(e,o))||t.enumerable});return a};var ne=a=>oe(P({},"__esModule",{value:!0}),a);var se={};ae(se,{createAppPageObject:()=>b,createPageObjects:()=>Q});module.exports=ne(se);var s=({page:a})=>{let e={continue:()=>a.getByRole("button",{name:"Continue",exact:!0}).click(),setEmailAddress:r=>e.getEmailAddressInput().fill(r),setPassword:r=>e.getPasswordInput().fill(r),setPasswordConfirmation:r=>a.locator("input[name=confirmPassword]").fill(r),enterOtpCode:async(r,t)=>{let{name:o="Enter verification code",awaitAttempt:n=!0,awaitPrepare:c=!0,awaitRequests:i=!0}=t??{};i&&c&&await a.waitForResponse(u=>u.request().method()==="POST"&&(u.url().includes("prepare_verification")||u.url().includes("prepare_first_factor")||u.url().includes("prepare_second_factor")));let l=a.getByRole("textbox",{name:"Enter verification code. Digit 1"});await l.isVisible()?(console.warn("Using the original OTP input"),await l.click(),await a.keyboard.type(r,{delay:100})):await a.getByLabel(o).fill(r),i&&n&&await a.waitForResponse(u=>u.request().method()==="POST"&&(u.url().includes("attempt_verification")||u.url().includes("attempt_first_factor")||u.url().includes("attempt_second_factor")))},enterTestOtpCode:async r=>e.enterOtpCode("424242",r),fillTestOtpCode:async(r,t)=>e.enterOtpCode("424242",{name:r,...t}),getIdentifierInput:()=>a.locator("input[name=identifier]"),getEmailAddressInput:()=>a.locator("input[name=emailAddress]"),getPhoneNumberInput:()=>a.locator("input[name=phoneNumber]"),getUsernameInput:()=>a.locator("input[name=username]"),getPasswordInput:()=>a.locator("input[name=password]"),getLegalAccepted:()=>a.locator("input[name=legalAccepted]"),getFirstNameInput:()=>a.locator("input[name=firstName]"),getLastNameInput:()=>a.locator("input[name=lastName]"),waitForSession:async()=>a.waitForFunction(()=>!!window.Clerk?.session)};return e};var B=a=>{let{page:e}=a,r={never:"Never","1d":"1 Day","7d":"7 Days","30d":"30 Days","60d":"60 Days","90d":"90 Days","180d":"180 Days","1y":"1 Year"};return{...s(a),waitForMounted:()=>e.waitForSelector(".cl-apiKeys-root",{state:"attached"}),clickAddButton:()=>e.getByText(/Add new key/i).click(),waitForFormOpened:()=>e.waitForSelector(".cl-apiKeysCreateForm",{state:"attached"}),waitForFormClosed:()=>e.waitForSelector(".cl-apiKeysCreateForm",{state:"detached"}),waitForRevokeModalOpened:()=>e.waitForSelector(".cl-apiKeysRevokeModal",{state:"attached"}),waitForRevokeModalClosed:()=>e.waitForSelector(".cl-apiKeysRevokeModal",{state:"detached"}),waitForCopyModalOpened:()=>e.waitForSelector(".cl-apiKeysCopyModal",{state:"attached"}),waitForCopyModalClosed:()=>e.waitForSelector(".cl-apiKeysCopyModal",{state:"detached"}),clickCopyAndCloseButton:()=>e.locator(".cl-apiKeysCopyModal .cl-apiKeysCopyModalSubmitButton").click(),typeName:o=>e.getByLabel(/Secret key name/i).fill(o),typeDescription:o=>e.getByLabel(/Description/i).fill(o),selectExpiration:async o=>(await e.getByRole("button",{name:/Select date/i}).click(),e.getByText(r[o??"never"],{exact:!0}).click({force:!0})),clickSaveButton:()=>e.getByText(/Create key/i).click(),typeRevokeConfirmation:o=>e.getByLabel(/Type "Revoke" to confirm/i).fill(o),clickConfirmRevokeButton:()=>e.getByText(/Revoke key/i).click()}};var E="__clerk_testing_token";var O="The Clerk Frontend API URL is required to bypass bot protection. Make sure the clerkSetup function is called during your global setup before setupClerkTestingToken is called.";var k=new WeakSet,ie=new Set([429,502,503,504]),f=3,x=500,U=250,y=async({context:a,options:e,page:r})=>{let t=a??r?.context();if(!t)throw new Error("Either context or page must be provided to setup testing token");if(k.has(t)){process.env.CLERK_TESTING_DEBUG&&console.log("[Clerk Testing] Route handler already registered for this context, skipping duplicate setup");return}let o=e?.frontendApiUrl||process.env.CLERK_FAPI;if(!o)throw new Error(O);let n=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`^https://${n}/v1/.*?(\\?.*)?$`);k.add(t);try{await t.route(c,async i=>{let l=new URL(i.request().url()),p=process.env.CLERK_TESTING_TOKEN;p&&l.searchParams.set(E,p);let u=l.toString();for(let m=0;m<=f;m++)try{let g=await i.fetch({url:u}),w=g.status();if(ie.has(w)){if(m<f){let h=x*Math.pow(2,m)+Math.random()*U;process.env.CLERK_TESTING_DEBUG&&console.log(`[Clerk Testing] FAPI returned ${w}, retrying (attempt ${m+1}/${f}, delay ${Math.round(h)}ms): ${i.request().url()}`),await new Promise(R=>setTimeout(R,h));continue}console.warn(`[Clerk Testing] FAPI request failed with status ${w} after ${f+1} attempts: ${i.request().url()}`),await i.fulfill({response:g});return}let d=await g.json();d?.response?.captcha_bypass===!1&&(d.response.captcha_bypass=!0),d?.client?.captcha_bypass===!1&&(d.client.captcha_bypass=!0),await i.fulfill({response:g,json:d});return}catch(g){if(m<f){let w=x*Math.pow(2,m)+Math.random()*U;process.env.CLERK_TESTING_DEBUG&&console.log(`[Clerk Testing] FAPI request error, retrying (attempt ${m+1}/${f}, delay ${Math.round(w)}ms): ${i.request().url()}`,g),await new Promise(d=>setTimeout(d,w));continue}console.warn(`[Clerk Testing] FAPI request failed after ${f+1} attempts: ${i.request().url()}`,g),await i.continue({url:u}).catch(console.error);return}})}catch(i){throw k.delete(t),i}};var b=(a,e)=>{let{page:r,useTestingToken:t=!0}=a,o=Object.create(r);return Object.assign(o,{goToAppHome:async()=>{if(!e.baseURL)throw new Error("Attempted to call method requiring baseURL, but baseURL was not provided to createPageObjects.");try{t&&await y({page:r}),await r.goto(e.baseURL)}catch{}},goToRelative:async(c,i={})=>{if(!e.baseURL)throw new Error("Attempted to call method requiring baseURL, but baseURL was not provided to createPageObjects.");let l;try{r.url().includes("about:blank")?l=new URL(c,e.baseURL):l=new URL(c,r.url())}catch{l=new URL(c,e.baseURL)}return i.searchParams&&(l.search=i.searchParams.toString()),t&&await y({page:r}),r.goto(l.toString(),{timeout:i.timeout??2e4,waitUntil:i.waitUntil})},waitForClerkJsLoaded:async()=>r.waitForFunction(()=>window.Clerk?.loaded),signOut:async()=>r.waitForFunction(()=>window.Clerk?.signOut({})),waitForClerkComponentMounted:async()=>r.waitForSelector(".cl-rootBox",{state:"attached"}),waitForAppUrl:async c=>{if(!e.baseURL)throw new Error("Attempted to call method requiring baseURL, but baseURL was not provided to createPageObjects.");return r.waitForURL(new URL(c,e.baseURL).toString())},cookies:async()=>{let c=await r.context().cookies(),i=c.reduce((l,p)=>(p.name.match(/^(__.*_)(.{8})$/)?l.set(p.name.replace(/^(__.*_)(.{8})$/,"$1*"),p):l.set(p.name,p),l),new Map);return Object.assign(i,{raw:()=>c})}})};var I=a=>{let{page:e}=a,r={...s(a),waitForMounted:(t=".cl-checkout-root")=>e.waitForSelector(t,{state:"attached",timeout:2e4}),closeDrawer:()=>e.locator(".cl-drawerClose").click(),fillTestCard:async()=>{await r.fillCard({number:"4242424242424242",expiration:"1234",cvc:"123",country:"United States",zip:"12345"})},fillCard:async t=>{await r.waitForStripeElements({state:"visible"});let o=e.frameLocator('iframe[src*="elements-inner-payment"]');await o.getByLabel("Card number").fill(t.number),await o.getByLabel("Expiration date").fill(t.expiration),await o.getByLabel("Security code").fill(t.cvc),await o.getByLabel("Country").selectOption(t.country),await o.getByLabel("ZIP code").fill(t.zip)},waitForStripeElements:async({state:t="visible"}={})=>{let o=e.locator('iframe[src*="elements-inner-payment"]');t==="visible"?(await o.waitFor({state:"attached",timeout:2e4}),await e.frameLocator('iframe[src*="elements-inner-payment"]').getByLabel("Card number").waitFor({state:"visible",timeout:2e4})):await e.frameLocator('iframe[src*="elements-inner-payment"]').getByLabel("Card number").waitFor({state:"hidden",timeout:2e4})},clickPayOrSubscribe:async()=>{await r.root.getByRole("button",{name:/subscribe|pay\s\$|start/i}).click()},waitForSubscribeButton:async()=>{await r.root.getByRole("button",{name:/^subscribe$/i}).waitFor({state:"visible"})},confirmAndContinue:async()=>{await r.root.getByRole("button",{name:/^continue$/i}).click()},clickAddPaymentMethod:async()=>{await r.root.getByRole("radio",{name:"Add payment method"}).click()},clickPaymentMethods:async()=>{await r.root.getByRole("radio",{name:"Payment Methods"}).click()},root:e.locator(".cl-checkout-root")};return r};var v=({page:a})=>({toBeLoaded:async()=>a.waitForFunction(()=>!!window.Clerk?.loaded),getClientSideActor:()=>a.evaluate(()=>window.Clerk?.session?.actor),toBeLoading:async()=>a.waitForFunction(()=>window.Clerk?.status==="loading"),toBeReady:async()=>a.waitForFunction(()=>window.Clerk?.status==="ready"),toBeDegraded:async()=>a.waitForFunction(()=>window.Clerk?.status==="degraded"),getClientSideUser:()=>a.evaluate(()=>window.Clerk?.user)});var F=require("@playwright/test"),A=({page:a})=>({toBeHandshake:async e=>{let r=await e.request().redirectedFrom()?.redirectedFrom()?.response();(0,F.expect)(r?.status()).toBe(307),(0,F.expect)(r?.headers()["x-clerk-auth-status"]).toContain("handshake")},toBeSignedOut:e=>a.waitForFunction(()=>window.Clerk?.user===null,null,{timeout:e?.timeOut}),toBeSignedIn:async()=>a.waitForFunction(()=>!!window.Clerk?.user),toBeSignedInAsActor:async()=>a.waitForFunction(()=>!!window.Clerk?.session?.actor),toHaveResolvedTask:async()=>a.waitForFunction(()=>!window.Clerk?.session?.currentTask)});var L=a=>{let{page:e}=a;return{waitForMounted:(t=".cl-impersonationFab")=>e.waitForSelector(t,{state:"attached"}),getSignOutLink:()=>e.locator(".cl-impersonationFab").getByText("Sign out")}};var M=a=>{let{page:e}=a,r=e.getByRole("button",{name:"Keyless prompt"});return{waitForMounted:()=>r.waitFor({state:"attached"}),waitForUnmounted:()=>r.waitFor({state:"detached"}),isExpanded:()=>r.getAttribute("aria-expanded").then(o=>o==="true"),toggle:()=>r.click(),promptsToClaim:()=>e.getByRole("link",{name:/^configure your application$/i}),promptToUseClaimedKeys:()=>e.getByRole("link",{name:/^get api keys$/i}),promptToDismiss:()=>e.getByRole("button",{name:/^dismiss$/i})}};var T=require("@playwright/test");var _=a=>{let{page:e}=a,r={...s(a),goTo:async(t="/switcher")=>(await e.goToRelative(t),r.waitForMounted()),waitForMounted:()=>e.waitForSelector(".cl-organizationSwitcher-root",{state:"attached"}),expectNoOrganizationSelected:()=>(0,T.expect)(e.getByText(/No organization selected/i)).toBeVisible(),expectPersonalAccount:()=>(0,T.expect)(e.getByText(/personal account/i)).toBeVisible(),toggleTrigger:()=>e.locator(".cl-organizationSwitcherTrigger").click(),waitForAnOrganizationToSelected:()=>e.waitForSelector(".cl-userPreviewMainIdentifier__personalWorkspace",{state:"detached"})};return r};var j=a=>{let{page:e}=a;return{...s(a),waitForMounted:(t=".cl-planDetails-root")=>e.waitForSelector(t,{state:"attached"}),root:e.locator(".cl-planDetails-root")}};var N=a=>{let{page:e}=a,r={toggle:n=>e.locator(`.cl-pricingTableCard__${n} .cl-pricingTableCardPeriodToggle`),indicator:n=>e.locator(`.cl-pricingTableCard__${n} .cl-switchIndicator`),badge:n=>e.locator(`.cl-pricingTableCard__${n} .cl-badge`),footer:n=>e.locator(`.cl-pricingTableCard__${n} .cl-pricingTableCardFooter`)},t=async(n,c)=>{async function i(p,u,m,g=5e3){return e.waitForFunction(({sel:w,attr:d,val:h})=>document.querySelector(w)?.getAttribute(d)===h,{sel:p,attr:u,val:m},{timeout:g}).then(()=>!0).catch(()=>!1)}let l=await i(`.cl-pricingTableCard__${n} .cl-switchIndicator`,"data-checked","true",500);l&&c==="monthly"&&await r.toggle(n).click(),!l&&c==="annually"&&await r.toggle(n).click()};return{...s(a),waitForMounted:(n=".cl-pricingTable-root")=>e.waitForSelector(n,{state:"attached"}),clickResubscribe:async()=>{await e.getByText("Re-subscribe").click()},waitToBeActive:async({planSlug:n})=>r.badge(n).getByText("Active").waitFor({state:"visible"}),waitToBeFreeTrial:async({planSlug:n})=>r.badge(n).getByText("Free trial").waitFor({state:"visible"}),getPlanCardCTA:({planSlug:n})=>r.footer(n).getByRole("button",{name:/get|switch|subscribe/i}),startCheckout:async({planSlug:n,shouldSwitch:c,period:i})=>{let l=c===!0?"Switch to this plan":c===!1?/subscribe/i:/get|switch|subscribe|Start \d+-day free trial/i;i&&await t(n,i),await r.footer(n).getByRole("button",{name:l}).click()}}};var S=require("@playwright/test");var $=a=>{let{page:e}=a;return{...s(a),resolveForceOrganizationSelectionTask:async t=>{let o=e.getByRole("button",{name:/continue/i});await(0,S.expect)(o).toBeVisible(),await e.locator("input[name=name]").fill(t.name),t.slug&&await e.locator("input[name=slug]").fill(t.slug),await o.click()},resolveResetPasswordTask:async({newPassword:t,confirmPassword:o})=>{await e.locator("input[name=newPassword]").fill(t),await e.locator("input[name=confirmPassword]").fill(o);let n=e.getByRole("button",{name:/reset password/i});await(0,S.expect)(n).toBeVisible(),await n.click()}}};var C=require("@playwright/test");var D=a=>{let{page:e}=a,r={...s(a),goTo:async t=>{let o=await e.goToRelative("/sign-in",t);return typeof t?.headlessSelector<"u"?await r.waitForMounted(t.headlessSelector):await r.waitForMounted(),o},waitForMounted:(t=".cl-signIn-root")=>e.waitForSelector(t,{state:"attached"}),waitForModal:t=>e.waitForSelector(".cl-modalContent:has(.cl-signIn-root)",{state:t==="closed"?"detached":"attached"}),setIdentifier:t=>r.getIdentifierInput().fill(t),setInstantPassword:async t=>{let o=r.getPasswordInput();await(0,C.expect)(o).toBeVisible(),await o.fill(t,{force:!0})},usePhoneNumberIdentifier:()=>e.getByRole("link",{name:/^use phone/i}),useEmailIdentifier:()=>e.getByRole("link",{name:/^use email/i}),useUsernameIdentifier:()=>e.getByRole("link",{name:/^username$/i}),getForgotPassword:()=>e.getByRole("link",{name:/forgot password/i}),getGoToSignUp:()=>e.getByRole("link",{name:/sign up/i}),getResetPassword:()=>e.getByRole("button",{name:/(reset password|reset your password)/i}),getUseAnotherMethodLink:()=>e.getByRole("link",{name:/use another method/i}),getAltMethodsEmailCodeButton:()=>e.getByRole("button",{name:/email code to/i}),getAltMethodsEmailLinkButton:()=>e.getByRole("button",{name:/email link to/i}),signInWithOauth:t=>e.getByRole("button",{name:new RegExp(`continue with ${t}`,"gi")}),signInWithEmailAndInstantPassword:async({email:t,password:o,waitForSession:n=!0})=>{let c=r.getIdentifierInput();await(0,C.expect)(c).toBeVisible(),await c.fill(t),await r.setInstantPassword(o),await r.continue(),n&&await r.waitForSession()}};return r};var K=a=>{let{page:e}=a,r={...s(a),goTo:async t=>(await e.goToRelative("/sign-up",{searchParams:t?.searchParams}),typeof t?.headlessSelector<"u"?r.waitForMounted(t.headlessSelector):r.waitForMounted()),waitForMounted:(t=".cl-signUp-root")=>e.waitForSelector(t,{state:"attached"}),waitForModal:t=>e.waitForSelector(".cl-modalContent:has(.cl-signUp-root)",{state:t==="closed"?"detached":"attached"}),signUpWithOauth:t=>e.getByRole("button",{name:new RegExp(`continue with ${t}`,"gi")}),signUp:async t=>{t.firstName&&await r.getFirstNameInput().fill(t.firstName),t.lastName&&await r.getLastNameInput().fill(t.lastName),t.email&&await r.getEmailAddressInput().fill(t.email),t.username&&await r.getUsernameInput().fill(t.username),t.phoneNumber&&await r.getPhoneNumberInput().fill(t.phoneNumber),t.password&&await r.getPasswordInput().fill(t.password),t.legalAccepted&&await r.getLegalAccepted().check(),await r.continue()},signUpWithEmailAndPassword:async t=>{await r.signUp({email:t.email,password:t.password})},waitForEmailVerificationScreen:async()=>{await e.waitForURL(/verify/),await e.getByRole("heading",{name:/Verify your email/i}).waitFor()}};return r};var V=a=>{let{page:e}=a,r={...s(a),waitForMounted:(t=".cl-subscriptionDetails-root")=>e.waitForSelector(t,{state:"attached"}),waitForUnmounted:()=>r.root.locator(".cl-drawerRoot").waitFor({state:"detached"}),closeDrawer:()=>r.root.locator(".cl-drawerClose").click(),root:e.locator(".cl-subscriptionDetails-root")};return r};var q=({page:a})=>({setup:async()=>y({page:a})});var G=require("@playwright/test"),W=".cl-userAvatarBox",z=a=>{let{page:e}=a,r={goTo:async t=>(await e.goToRelative("/user-avatar",t),r.waitForMounted()),waitForMounted:(t=W)=>e.waitForSelector(t,{state:"attached"}),toBeVisible:async(t=W)=>await(0,G.expect)(e.locator(t).getByRole("img")).toBeVisible()};return r};var H=require("@playwright/test"),J=a=>{let{page:e}=a;return{waitForMounted:()=>e.waitForSelector(".cl-userButtonTrigger",{state:"attached"}),toggleTrigger:()=>e.locator(".cl-userButtonTrigger").click(),waitForPopover:()=>e.waitForSelector(".cl-userButtonPopoverCard",{state:"visible"}),waitForPopoverClosed:()=>e.waitForSelector(".cl-userButtonPopoverCard",{state:"detached"}),toHaveVisibleMenuItems:async t=>{(typeof t=="string"||t instanceof RegExp)&&(t=[t]);for(let o of t)await(0,H.expect)(e.getByRole("menuitem",{name:o})).toBeVisible()},triggerSignOut:()=>e.getByRole("menuitem",{name:/Sign out$/i}).click(),triggerManageAccount:()=>e.getByRole("menuitem",{name:/Manage account/i}).click(),switchAccount:t=>e.getByText(t).click()}};var Y=a=>{let{page:e}=a,r={...s(a),goTo:async t=>(await e.goToRelative("/user",t),r.waitForMounted()),switchToSecurityTab:async()=>{await e.getByText(/Security/i).click()},switchToBillingTab:async()=>{await e.getByText(/Billing/i).click()},switchToAPIKeysTab:async()=>{await e.getByText(/API keys/i).click()},waitForMounted:()=>e.waitForSelector(".cl-userProfile-root",{state:"attached"}),clickSetUsername:()=>e.getByText(/Set username/i).click(),clickToUpdateProfile:()=>e.getByText(/update profile/i).click(),clickUpdateUsername:()=>e.getByText(/update username/i).click(),clickSetPassword:()=>e.getByText(/Set password/i).click(),waitForSectionCard:(t,o)=>e.waitForSelector(`.cl-profileSectionContent__${t} .cl-headerTitle`,{state:o?"visible":"detached"}),waitForSectionCardOpened:t=>r.waitForSectionCard(t,!0),waitForSectionCardClosed:t=>r.waitForSectionCard(t,!1),typeUsername:t=>r.getUsernameInput().fill(t),typeFirstName:t=>r.getFirstNameInput().fill(t),typeLastName:t=>r.getLastNameInput().fill(t),typePhoneNumber:t=>r.getPhoneNumberInput().fill(t),clickAddEmailAddress:()=>e.getByText(/add email address/i).click(),clickAddPhoneNumber:()=>e.getByText(/add phone number/i).click(),typeEmailAddress:t=>e.getByLabel(/Email address/i).fill(t),waitForUserProfileModal:t=>e.waitForSelector(".cl-modalContent:has(.cl-userProfile-root)",{state:t==="closed"?"detached":"attached"})};return r};var X=a=>{let{page:e}=a;return{...s(a),waitForMounted:(t=".cl-userVerification-root")=>e.waitForSelector(t,{state:"attached"}),waitForClosed:(t=".cl-userVerification-root")=>e.waitForSelector(t,{state:"detached"}),closeReverificationModal:()=>e.getByLabel("Close modal").click(),getUseAnotherMethodLink:()=>e.getByRole("link",{name:/use another method/i}),getAltMethodsEmailCodeButton:()=>e.getByRole("button",{name:/email code to/i}),getAltMethodsEmailLinkButton:()=>e.getByRole("button",{name:/email link to/i})}};var Z=a=>{let{page:e}=a,r={...s(a),goTo:async t=>(await e.goToRelative("/waitlist",{searchParams:t?.searchParams}),typeof t?.headlessSelector<"u"?r.waitForMounted(t.headlessSelector):r.waitForMounted()),waitForMounted:(t=".cl-waitlist-root")=>e.waitForSelector(t,{state:"attached"}),joinWaitlist:async t=>{await r.getEmailAddressInput().fill(t.email),await r.joinWaitlistContinue()},joinWaitlistContinue:()=>e.getByRole("button",{name:"Join the waitlist",exact:!0}).click()};return r};var Q=({page:a,useTestingToken:e=!0,baseURL:r})=>{let t=b({page:a,useTestingToken:e},{baseURL:r}),o={page:t};return{page:t,clerk:v(o),checkout:I(o),expect:A(o),impersonation:L(o),keylessPopover:M(o),organizationSwitcher:_(o),pricingTable:N(o),sessionTask:$(o),signIn:D(o),signUp:K(o),testingToken:q(o),userAvatar:z(o),userButton:J(o),userProfile:Y(o),userVerification:X(o),waitlist:Z(o),apiKeys:B(o),subscriptionDetails:V(o),planDetails:j(o)}};0&&(module.exports={createAppPageObject,createPageObjects}); //# sourceMappingURL=index.js.map