{"version":3,"sources":["../../src/utilities/getSafeRedirect.spec.ts"],"sourcesContent":["import { describe, it, expect } from 'vitest'\nimport { getSafeRedirect } from './getSafeRedirect'\n\nconst fallback = '/admin' // default fallback if the input is unsafe or invalid\n\ndescribe('getSafeRedirect', () => {\n // Valid - safe redirect paths\n it.each([['/dashboard'], ['/admin/settings'], ['/projects?id=123'], ['/hello-world']])(\n 'should allow safe relative path: %s',\n (input) => {\n // If the input is a clean relative path, it should be returned as-is\n expect(getSafeRedirect({ redirectTo: input, fallbackTo: fallback })).toBe(input)\n },\n )\n\n // Invalid types or empty inputs\n it.each(['', null, undefined, 123, {}, []])(\n 'should fallback on invalid or non-string input: %s',\n (input) => {\n // If the input is not a valid string, it should return the fallback\n expect(getSafeRedirect({ redirectTo: input as any, fallbackTo: fallback })).toBe(fallback)\n },\n )\n\n // Unsafe redirect patterns\n it.each([\n '//example.com', // protocol-relative URL\n '/javascript:alert(1)', // JavaScript scheme\n '/JavaScript:alert(1)', // case-insensitive JavaScript\n '/http://unknown.com', // disguised external redirect\n '/https://unknown.com', // disguised external redirect\n '/%2Funknown.com', // encoded slash — could resolve to //\n '/\\\\/unknown.com', // escaped slash\n '/\\\\\\\\unknown.com', // double escaped slashes\n '/\\\\unknown.com', // single escaped slash\n '%2F%2Funknown.com', // fully encoded protocol-relative path\n '%2Fjavascript:alert(1)', // encoded JavaScript scheme\n ])('should block unsafe redirect: %s', (input) => {\n // All of these should return the fallback because they’re unsafe\n expect(getSafeRedirect({ redirectTo: input, fallbackTo: fallback })).toBe(fallback)\n })\n\n // Input with extra spaces should still be properly handled\n it('should trim whitespace before evaluating', () => {\n // A valid path with surrounding spaces should still be accepted\n expect(getSafeRedirect({ redirectTo: ' /dashboard ', fallbackTo: fallback })).toBe(\n '/dashboard',\n )\n\n // An unsafe path with spaces should still be rejected\n expect(getSafeRedirect({ redirectTo: ' //example.com ', fallbackTo: fallback })).toBe(\n fallback,\n )\n })\n\n // If decoding the input fails (e.g., invalid percent encoding), it should not crash\n it('should return fallback on invalid encoding', () => {\n expect(getSafeRedirect({ redirectTo: '%E0%A4%A', fallbackTo: fallback })).toBe(fallback)\n })\n})\n"],"names":["describe","it","expect","getSafeRedirect","fallback","each","input","redirectTo","fallbackTo","toBe","undefined"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,EAAE,EAAEC,MAAM,QAAQ,SAAQ;AAC7C,SAASC,eAAe,QAAQ,oBAAmB;AAEnD,MAAMC,WAAW,SAAS,qDAAqD;;AAE/EJ,SAAS,mBAAmB;IAC1B,8BAA8B;IAC9BC,GAAGI,IAAI,CAAC;QAAC;YAAC;SAAa;QAAE;YAAC;SAAkB;QAAE;YAAC;SAAmB;QAAE;YAAC;SAAe;KAAC,EACnF,uCACA,CAACC;QACC,qEAAqE;QACrEJ,OAAOC,gBAAgB;YAAEI,YAAYD;YAAOE,YAAYJ;QAAS,IAAIK,IAAI,CAACH;IAC5E;IAGF,gCAAgC;IAChCL,GAAGI,IAAI,CAAC;QAAC;QAAI;QAAMK;QAAW;QAAK,CAAC;QAAG,EAAE;KAAC,EACxC,sDACA,CAACJ;QACC,oEAAoE;QACpEJ,OAAOC,gBAAgB;YAAEI,YAAYD;YAAcE,YAAYJ;QAAS,IAAIK,IAAI,CAACL;IACnF;IAGF,2BAA2B;IAC3BH,GAAGI,IAAI,CAAC;QACN;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;KACD,EAAE,oCAAoC,CAACC;QACtC,iEAAiE;QACjEJ,OAAOC,gBAAgB;YAAEI,YAAYD;YAAOE,YAAYJ;QAAS,IAAIK,IAAI,CAACL;IAC5E;IAEA,2DAA2D;IAC3DH,GAAG,4CAA4C;QAC7C,gEAAgE;QAChEC,OAAOC,gBAAgB;YAAEI,YAAY;YAAoBC,YAAYJ;QAAS,IAAIK,IAAI,CACpF;QAGF,sDAAsD;QACtDP,OAAOC,gBAAgB;YAAEI,YAAY;YAAuBC,YAAYJ;QAAS,IAAIK,IAAI,CACvFL;IAEJ;IAEA,oFAAoF;IACpFH,GAAG,8CAA8C;QAC/CC,OAAOC,gBAAgB;YAAEI,YAAY;YAAYC,YAAYJ;QAAS,IAAIK,IAAI,CAACL;IACjF;AACF"}