 aacb45156b
			
		
	
	aacb45156b
	
	
	
		
			
			- Install Jest for unit testing with React Testing Library - Install Playwright for end-to-end testing - Configure Jest with proper TypeScript support and module mapping - Create test setup files and utilities for both unit and e2e tests Components: * Jest configuration with coverage thresholds * Playwright configuration with browser automation * Unit tests for LoginForm, AuthContext, and useSocketIO hook * E2E tests for authentication, dashboard, and agents workflows * GitHub Actions workflow for automated testing * Mock data and API utilities for consistent testing * Test documentation with best practices Testing features: - Unit tests with 70% coverage threshold - E2E tests with API mocking and user journey testing - CI/CD integration for automated test runs - Cross-browser testing support with Playwright - Authentication system testing end-to-end 🚀 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			143 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| const { isASCIIHex } = require("./infra");
 | |
| const { utf8Encode } = require("./encoding");
 | |
| 
 | |
| function p(char) {
 | |
|   return char.codePointAt(0);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#percent-encode
 | |
| function percentEncode(c) {
 | |
|   let hex = c.toString(16).toUpperCase();
 | |
|   if (hex.length === 1) {
 | |
|     hex = `0${hex}`;
 | |
|   }
 | |
| 
 | |
|   return `%${hex}`;
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#percent-decode
 | |
| function percentDecodeBytes(input) {
 | |
|   const output = new Uint8Array(input.byteLength);
 | |
|   let outputIndex = 0;
 | |
|   for (let i = 0; i < input.byteLength; ++i) {
 | |
|     const byte = input[i];
 | |
|     if (byte !== 0x25) {
 | |
|       output[outputIndex++] = byte;
 | |
|     } else if (byte === 0x25 && (!isASCIIHex(input[i + 1]) || !isASCIIHex(input[i + 2]))) {
 | |
|       output[outputIndex++] = byte;
 | |
|     } else {
 | |
|       const bytePoint = parseInt(String.fromCodePoint(input[i + 1], input[i + 2]), 16);
 | |
|       output[outputIndex++] = bytePoint;
 | |
|       i += 2;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return output.slice(0, outputIndex);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#string-percent-decode
 | |
| function percentDecodeString(input) {
 | |
|   const bytes = utf8Encode(input);
 | |
|   return percentDecodeBytes(bytes);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#c0-control-percent-encode-set
 | |
| function isC0ControlPercentEncode(c) {
 | |
|   return c <= 0x1F || c > 0x7E;
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#fragment-percent-encode-set
 | |
| const extraFragmentPercentEncodeSet = new Set([p(" "), p("\""), p("<"), p(">"), p("`")]);
 | |
| function isFragmentPercentEncode(c) {
 | |
|   return isC0ControlPercentEncode(c) || extraFragmentPercentEncodeSet.has(c);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#query-percent-encode-set
 | |
| const extraQueryPercentEncodeSet = new Set([p(" "), p("\""), p("#"), p("<"), p(">")]);
 | |
| function isQueryPercentEncode(c) {
 | |
|   return isC0ControlPercentEncode(c) || extraQueryPercentEncodeSet.has(c);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#special-query-percent-encode-set
 | |
| function isSpecialQueryPercentEncode(c) {
 | |
|   return isQueryPercentEncode(c) || c === p("'");
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#path-percent-encode-set
 | |
| const extraPathPercentEncodeSet = new Set([p("?"), p("`"), p("{"), p("}"), p("^")]);
 | |
| function isPathPercentEncode(c) {
 | |
|   return isQueryPercentEncode(c) || extraPathPercentEncodeSet.has(c);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#userinfo-percent-encode-set
 | |
| const extraUserinfoPercentEncodeSet =
 | |
|   new Set([p("/"), p(":"), p(";"), p("="), p("@"), p("["), p("\\"), p("]"), p("|")]);
 | |
| function isUserinfoPercentEncode(c) {
 | |
|   return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#component-percent-encode-set
 | |
| const extraComponentPercentEncodeSet = new Set([p("$"), p("%"), p("&"), p("+"), p(",")]);
 | |
| function isComponentPercentEncode(c) {
 | |
|   return isUserinfoPercentEncode(c) || extraComponentPercentEncodeSet.has(c);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#application-x-www-form-urlencoded-percent-encode-set
 | |
| const extraURLEncodedPercentEncodeSet = new Set([p("!"), p("'"), p("("), p(")"), p("~")]);
 | |
| function isURLEncodedPercentEncode(c) {
 | |
|   return isComponentPercentEncode(c) || extraURLEncodedPercentEncodeSet.has(c);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#code-point-percent-encode-after-encoding
 | |
| // https://url.spec.whatwg.org/#utf-8-percent-encode
 | |
| // Assuming encoding is always utf-8 allows us to trim one of the logic branches. TODO: support encoding.
 | |
| // The "-Internal" variant here has code points as JS strings. The external version used by other files has code points
 | |
| // as JS numbers, like the rest of the codebase.
 | |
| function utf8PercentEncodeCodePointInternal(codePoint, percentEncodePredicate) {
 | |
|   const bytes = utf8Encode(codePoint);
 | |
|   let output = "";
 | |
|   for (const byte of bytes) {
 | |
|     // Our percentEncodePredicate operates on bytes, not code points, so this is slightly different from the spec.
 | |
|     if (!percentEncodePredicate(byte)) {
 | |
|       output += String.fromCharCode(byte);
 | |
|     } else {
 | |
|       output += percentEncode(byte);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return output;
 | |
| }
 | |
| 
 | |
| function utf8PercentEncodeCodePoint(codePoint, percentEncodePredicate) {
 | |
|   return utf8PercentEncodeCodePointInternal(String.fromCodePoint(codePoint), percentEncodePredicate);
 | |
| }
 | |
| 
 | |
| // https://url.spec.whatwg.org/#string-percent-encode-after-encoding
 | |
| // https://url.spec.whatwg.org/#string-utf-8-percent-encode
 | |
| function utf8PercentEncodeString(input, percentEncodePredicate, spaceAsPlus = false) {
 | |
|   let output = "";
 | |
|   for (const codePoint of input) {
 | |
|     if (spaceAsPlus && codePoint === " ") {
 | |
|       output += "+";
 | |
|     } else {
 | |
|       output += utf8PercentEncodeCodePointInternal(codePoint, percentEncodePredicate);
 | |
|     }
 | |
|   }
 | |
|   return output;
 | |
| }
 | |
| 
 | |
| module.exports = {
 | |
|   isC0ControlPercentEncode,
 | |
|   isFragmentPercentEncode,
 | |
|   isQueryPercentEncode,
 | |
|   isSpecialQueryPercentEncode,
 | |
|   isPathPercentEncode,
 | |
|   isUserinfoPercentEncode,
 | |
|   isURLEncodedPercentEncode,
 | |
|   percentDecodeString,
 | |
|   percentDecodeBytes,
 | |
|   utf8PercentEncodeString,
 | |
|   utf8PercentEncodeCodePoint
 | |
| };
 |