Best JavaScript code snippet using playwright-internal
DOMProperty.js
Source:DOMProperty.js
1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @flow8 */9import {enableDeprecatedFlareAPI} from 'shared/ReactFeatureFlags';10type PropertyType = 0 | 1 | 2 | 3 | 4 | 5 | 6;11// A reserved attribute.12// It is handled by React separately and shouldn't be written to the DOM.13export const RESERVED = 0;14// A simple string attribute.15// Attributes that aren't in the whitelist are presumed to have this type.16export const STRING = 1;17// A string attribute that accepts booleans in React. In HTML, these are called18// "enumerated" attributes with "true" and "false" as possible values.19// When true, it should be set to a "true" string.20// When false, it should be set to a "false" string.21export const BOOLEANISH_STRING = 2;22// A real boolean attribute.23// When true, it should be present (set either to an empty string or its name).24// When false, it should be omitted.25export const BOOLEAN = 3;26// An attribute that can be used as a flag as well as with a value.27// When true, it should be present (set either to an empty string or its name).28// When false, it should be omitted.29// For any other value, should be present with that value.30export const OVERLOADED_BOOLEAN = 4;31// An attribute that must be numeric or parse as a numeric.32// When falsy, it should be removed.33export const NUMERIC = 5;34// An attribute that must be positive numeric or parse as a positive numeric.35// When falsy, it should be removed.36export const POSITIVE_NUMERIC = 6;37export type PropertyInfo = {|38 +acceptsBooleans: boolean,39 +attributeName: string,40 +attributeNamespace: string | null,41 +mustUseProperty: boolean,42 +propertyName: string,43 +type: PropertyType,44 +sanitizeURL: boolean,45|};46/* eslint-disable max-len */47export const ATTRIBUTE_NAME_START_CHAR =48 ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';49/* eslint-enable max-len */50export const ATTRIBUTE_NAME_CHAR =51 ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';52export const ID_ATTRIBUTE_NAME = 'data-reactid';53export const ROOT_ATTRIBUTE_NAME = 'data-reactroot';54export const VALID_ATTRIBUTE_NAME_REGEX = new RegExp(55 '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',56);57const hasOwnProperty = Object.prototype.hasOwnProperty;58const illegalAttributeNameCache = {};59const validatedAttributeNameCache = {};60export function isAttributeNameSafe(attributeName: string): boolean {61 if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {62 return true;63 }64 if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) {65 return false;66 }67 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {68 validatedAttributeNameCache[attributeName] = true;69 return true;70 }71 illegalAttributeNameCache[attributeName] = true;72 if (__DEV__) {73 console.error('Invalid attribute name: `%s`', attributeName);74 }75 return false;76}77export function shouldIgnoreAttribute(78 name: string,79 propertyInfo: PropertyInfo | null,80 isCustomComponentTag: boolean,81): boolean {82 if (propertyInfo !== null) {83 return propertyInfo.type === RESERVED;84 }85 if (isCustomComponentTag) {86 return false;87 }88 if (89 name.length > 2 &&90 (name[0] === 'o' || name[0] === 'O') &&91 (name[1] === 'n' || name[1] === 'N')92 ) {93 return true;94 }95 return false;96}97export function shouldRemoveAttributeWithWarning(98 name: string,99 value: mixed,100 propertyInfo: PropertyInfo | null,101 isCustomComponentTag: boolean,102): boolean {103 if (propertyInfo !== null && propertyInfo.type === RESERVED) {104 return false;105 }106 switch (typeof value) {107 case 'function':108 // $FlowIssue symbol is perfectly valid here109 case 'symbol': // eslint-disable-line110 return true;111 case 'boolean': {112 if (isCustomComponentTag) {113 return false;114 }115 if (propertyInfo !== null) {116 return !propertyInfo.acceptsBooleans;117 } else {118 const prefix = name.toLowerCase().slice(0, 5);119 return prefix !== 'data-' && prefix !== 'aria-';120 }121 }122 default:123 return false;124 }125}126export function shouldRemoveAttribute(127 name: string,128 value: mixed,129 propertyInfo: PropertyInfo | null,130 isCustomComponentTag: boolean,131): boolean {132 if (value === null || typeof value === 'undefined') {133 return true;134 }135 if (136 shouldRemoveAttributeWithWarning(137 name,138 value,139 propertyInfo,140 isCustomComponentTag,141 )142 ) {143 return true;144 }145 if (isCustomComponentTag) {146 return false;147 }148 if (propertyInfo !== null) {149 switch (propertyInfo.type) {150 case BOOLEAN:151 return !value;152 case OVERLOADED_BOOLEAN:153 return value === false;154 case NUMERIC:155 return isNaN(value);156 case POSITIVE_NUMERIC:157 return isNaN(value) || (value: any) < 1;158 }159 }160 return false;161}162export function getPropertyInfo(name: string): PropertyInfo | null {163 return properties.hasOwnProperty(name) ? properties[name] : null;164}165function PropertyInfoRecord(166 name: string,167 type: PropertyType,168 mustUseProperty: boolean,169 attributeName: string,170 attributeNamespace: string | null,171 sanitizeURL: boolean,172) {173 this.acceptsBooleans =174 type === BOOLEANISH_STRING ||175 type === BOOLEAN ||176 type === OVERLOADED_BOOLEAN;177 this.attributeName = attributeName;178 this.attributeNamespace = attributeNamespace;179 this.mustUseProperty = mustUseProperty;180 this.propertyName = name;181 this.type = type;182 this.sanitizeURL = sanitizeURL;183}184// When adding attributes to this list, be sure to also add them to185// the `possibleStandardNames` module to ensure casing and incorrect186// name warnings.187const properties = {};188// These props are reserved by React. They shouldn't be written to the DOM.189const reservedProps = [190 'children',191 'dangerouslySetInnerHTML',192 // TODO: This prevents the assignment of defaultValue to regular193 // elements (not just inputs). Now that ReactDOMInput assigns to the194 // defaultValue property -- do we need this?195 'defaultValue',196 'defaultChecked',197 'innerHTML',198 'suppressContentEditableWarning',199 'suppressHydrationWarning',200 'style',201];202if (enableDeprecatedFlareAPI) {203 reservedProps.push('DEPRECATED_flareListeners');204}205reservedProps.forEach(name => {206 properties[name] = new PropertyInfoRecord(207 name,208 RESERVED,209 false, // mustUseProperty210 name, // attributeName211 null, // attributeNamespace212 false, // sanitizeURL213 );214});215// A few React string attributes have a different name.216// This is a mapping from React prop names to the attribute names.217[218 ['acceptCharset', 'accept-charset'],219 ['className', 'class'],220 ['htmlFor', 'for'],221 ['httpEquiv', 'http-equiv'],222].forEach(([name, attributeName]) => {223 properties[name] = new PropertyInfoRecord(224 name,225 STRING,226 false, // mustUseProperty227 attributeName, // attributeName228 null, // attributeNamespace229 false, // sanitizeURL230 );231});232// These are "enumerated" HTML attributes that accept "true" and "false".233// In React, we let users pass `true` and `false` even though technically234// these aren't boolean attributes (they are coerced to strings).235['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(name => {236 properties[name] = new PropertyInfoRecord(237 name,238 BOOLEANISH_STRING,239 false, // mustUseProperty240 name.toLowerCase(), // attributeName241 null, // attributeNamespace242 false, // sanitizeURL243 );244});245// These are "enumerated" SVG attributes that accept "true" and "false".246// In React, we let users pass `true` and `false` even though technically247// these aren't boolean attributes (they are coerced to strings).248// Since these are SVG attributes, their attribute names are case-sensitive.249[250 'autoReverse',251 'externalResourcesRequired',252 'focusable',253 'preserveAlpha',254].forEach(name => {255 properties[name] = new PropertyInfoRecord(256 name,257 BOOLEANISH_STRING,258 false, // mustUseProperty259 name, // attributeName260 null, // attributeNamespace261 false, // sanitizeURL262 );263});264// These are HTML boolean attributes.265[266 'allowFullScreen',267 'async',268 // Note: there is a special case that prevents it from being written to the DOM269 // on the client side because the browsers are inconsistent. Instead we call focus().270 'autoFocus',271 'autoPlay',272 'controls',273 'default',274 'defer',275 'disabled',276 'disablePictureInPicture',277 'formNoValidate',278 'hidden',279 'loop',280 'noModule',281 'noValidate',282 'open',283 'playsInline',284 'readOnly',285 'required',286 'reversed',287 'scoped',288 'seamless',289 // Microdata290 'itemScope',291].forEach(name => {292 properties[name] = new PropertyInfoRecord(293 name,294 BOOLEAN,295 false, // mustUseProperty296 name.toLowerCase(), // attributeName297 null, // attributeNamespace298 false, // sanitizeURL299 );300});301// These are the few React props that we set as DOM properties302// rather than attributes. These are all booleans.303[304 'checked',305 // Note: `option.selected` is not updated if `select.multiple` is306 // disabled with `removeAttribute`. We have special logic for handling this.307 'multiple',308 'muted',309 'selected',310 // NOTE: if you add a camelCased prop to this list,311 // you'll need to set attributeName to name.toLowerCase()312 // instead in the assignment below.313].forEach(name => {314 properties[name] = new PropertyInfoRecord(315 name,316 BOOLEAN,317 true, // mustUseProperty318 name, // attributeName319 null, // attributeNamespace320 false, // sanitizeURL321 );322});323// These are HTML attributes that are "overloaded booleans": they behave like324// booleans, but can also accept a string value.325[326 'capture',327 'download',328 // NOTE: if you add a camelCased prop to this list,329 // you'll need to set attributeName to name.toLowerCase()330 // instead in the assignment below.331].forEach(name => {332 properties[name] = new PropertyInfoRecord(333 name,334 OVERLOADED_BOOLEAN,335 false, // mustUseProperty336 name, // attributeName337 null, // attributeNamespace338 false, // sanitizeURL339 );340});341// These are HTML attributes that must be positive numbers.342[343 'cols',344 'rows',345 'size',346 'span',347 // NOTE: if you add a camelCased prop to this list,348 // you'll need to set attributeName to name.toLowerCase()349 // instead in the assignment below.350].forEach(name => {351 properties[name] = new PropertyInfoRecord(352 name,353 POSITIVE_NUMERIC,354 false, // mustUseProperty355 name, // attributeName356 null, // attributeNamespace357 false, // sanitizeURL358 );359});360// These are HTML attributes that must be numbers.361['rowSpan', 'start'].forEach(name => {362 properties[name] = new PropertyInfoRecord(363 name,364 NUMERIC,365 false, // mustUseProperty366 name.toLowerCase(), // attributeName367 null, // attributeNamespace368 false, // sanitizeURL369 );370});371const CAMELIZE = /[\-\:]([a-z])/g;372const capitalize = token => token[1].toUpperCase();373// This is a list of all SVG attributes that need special casing, namespacing,374// or boolean value assignment. Regular attributes that just accept strings375// and have the same names are omitted, just like in the HTML whitelist.376// Some of these attributes can be hard to find. This list was created by377// scrapping the MDN documentation.378[379 'accent-height',380 'alignment-baseline',381 'arabic-form',382 'baseline-shift',383 'cap-height',384 'clip-path',385 'clip-rule',386 'color-interpolation',387 'color-interpolation-filters',388 'color-profile',389 'color-rendering',390 'dominant-baseline',391 'enable-background',392 'fill-opacity',393 'fill-rule',394 'flood-color',395 'flood-opacity',396 'font-family',397 'font-size',398 'font-size-adjust',399 'font-stretch',400 'font-style',401 'font-variant',402 'font-weight',403 'glyph-name',404 'glyph-orientation-horizontal',405 'glyph-orientation-vertical',406 'horiz-adv-x',407 'horiz-origin-x',408 'image-rendering',409 'letter-spacing',410 'lighting-color',411 'marker-end',412 'marker-mid',413 'marker-start',414 'overline-position',415 'overline-thickness',416 'paint-order',417 'panose-1',418 'pointer-events',419 'rendering-intent',420 'shape-rendering',421 'stop-color',422 'stop-opacity',423 'strikethrough-position',424 'strikethrough-thickness',425 'stroke-dasharray',426 'stroke-dashoffset',427 'stroke-linecap',428 'stroke-linejoin',429 'stroke-miterlimit',430 'stroke-opacity',431 'stroke-width',432 'text-anchor',433 'text-decoration',434 'text-rendering',435 'underline-position',436 'underline-thickness',437 'unicode-bidi',438 'unicode-range',439 'units-per-em',440 'v-alphabetic',441 'v-hanging',442 'v-ideographic',443 'v-mathematical',444 'vector-effect',445 'vert-adv-y',446 'vert-origin-x',447 'vert-origin-y',448 'word-spacing',449 'writing-mode',450 'xmlns:xlink',451 'x-height',452 // NOTE: if you add a camelCased prop to this list,453 // you'll need to set attributeName to name.toLowerCase()454 // instead in the assignment below.455].forEach(attributeName => {456 const name = attributeName.replace(CAMELIZE, capitalize);457 properties[name] = new PropertyInfoRecord(458 name,459 STRING,460 false, // mustUseProperty461 attributeName,462 null, // attributeNamespace463 false, // sanitizeURL464 );465});466// String SVG attributes with the xlink namespace.467[468 'xlink:actuate',469 'xlink:arcrole',470 'xlink:role',471 'xlink:show',472 'xlink:title',473 'xlink:type',474 // NOTE: if you add a camelCased prop to this list,475 // you'll need to set attributeName to name.toLowerCase()476 // instead in the assignment below.477].forEach(attributeName => {478 const name = attributeName.replace(CAMELIZE, capitalize);479 properties[name] = new PropertyInfoRecord(480 name,481 STRING,482 false, // mustUseProperty483 attributeName,484 'http://www.w3.org/1999/xlink',485 false, // sanitizeURL486 );487});488// String SVG attributes with the xml namespace.489[490 'xml:base',491 'xml:lang',492 'xml:space',493 // NOTE: if you add a camelCased prop to this list,494 // you'll need to set attributeName to name.toLowerCase()495 // instead in the assignment below.496].forEach(attributeName => {497 const name = attributeName.replace(CAMELIZE, capitalize);498 properties[name] = new PropertyInfoRecord(499 name,500 STRING,501 false, // mustUseProperty502 attributeName,503 'http://www.w3.org/XML/1998/namespace',504 false, // sanitizeURL505 );506});507// These attribute exists both in HTML and SVG.508// The attribute name is case-sensitive in SVG so we can't just use509// the React name like we do for attributes that exist only in HTML.510['tabIndex', 'crossOrigin'].forEach(attributeName => {511 properties[attributeName] = new PropertyInfoRecord(512 attributeName,513 STRING,514 false, // mustUseProperty515 attributeName.toLowerCase(), // attributeName516 null, // attributeNamespace517 false, // sanitizeURL518 );519});520// These attributes accept URLs. These must not allow javascript: URLS.521// These will also need to accept Trusted Types object in the future.522const xlinkHref = 'xlinkHref';523properties[xlinkHref] = new PropertyInfoRecord(524 'xlinkHref',525 STRING,526 false, // mustUseProperty527 'xlink:href',528 'http://www.w3.org/1999/xlink',529 true, // sanitizeURL530);531['src', 'href', 'action', 'formAction'].forEach(attributeName => {532 properties[attributeName] = new PropertyInfoRecord(533 attributeName,534 STRING,535 false, // mustUseProperty536 attributeName.toLowerCase(), // attributeName537 null, // attributeNamespace538 true, // sanitizeURL539 );...
sanitize-url.spec.ts
Source:sanitize-url.spec.ts
1import { sanitizeUrl } from "./sanitize-url";2describe("sanitizeUrl", () => {3 it("does not alter http URLs with alphanumeric characters", () => {4 expect(5 sanitizeUrl("http://example.com/path/to:something"),6 ).toBe("http://example.com/path/to:something");7 });8 it("does not alter http URLs with ports with alphanumeric characters", () => {9 expect(10 sanitizeUrl(11 "http://example.com:4567/path/to:something",12 ),13 ).toBe("http://example.com:4567/path/to:something");14 });15 it("does not alter https URLs with alphanumeric characters", () => {16 expect(sanitizeUrl("https://example.com")).toBe(17 "https://example.com",18 );19 });20 it("does not alter https URLs with ports with alphanumeric characters", () => {21 expect(22 sanitizeUrl(23 "https://example.com:4567/path/to:something",24 ),25 ).toBe("https://example.com:4567/path/to:something");26 });27 it("does not alter relative-path reference URLs with alphanumeric characters", () => {28 expect(sanitizeUrl("./path/to/my.json")).toBe(29 "./path/to/my.json",30 );31 });32 it("does not alter absolute-path reference URLs with alphanumeric characters", () => {33 expect(sanitizeUrl("/path/to/my.json")).toBe(34 "/path/to/my.json",35 );36 });37 it("does not alter protocol-less network-path URLs with alphanumeric characters", () => {38 expect(sanitizeUrl("//google.com/robots.txt")).toBe(39 "//google.com/robots.txt",40 );41 });42 it("does not alter protocol-less URLs with alphanumeric characters", () => {43 expect(sanitizeUrl("www.example.com")).toBe(44 "www.example.com",45 );46 });47 it("does not alter deep-link urls with alphanumeric characters", () => {48 expect(49 sanitizeUrl("com.braintreepayments.demo://example"),50 ).toBe("com.braintreepayments.demo://example");51 });52 it("does not alter mailto urls with alphanumeric characters", () => {53 expect(54 sanitizeUrl(55 "mailto:test@example.com?subject=hello+world",56 ),57 ).toBe("mailto:test@example.com?subject=hello+world");58 });59 it("does not alter urls with accented characters", () => {60 expect(61 sanitizeUrl("www.example.com/with-áccêntÅ¡"),62 ).toBe("www.example.com/with-áccêntÅ¡");63 });64 it("does not strip harmless unicode characters", () => {65 expect(66 sanitizeUrl("www.example.com/лоÑ.ÑÑÑиÑкиüâ"),67 ).toBe("www.example.com/лоÑ.ÑÑÑиÑкиüâ");68 });69 it("strips out ctrl chars", () => {70 expect(71 sanitizeUrl(72 "www.example.com/\u200D\u0000\u001F\x00\x1F\uFEFFfoo",73 ),74 ).toBe("www.example.com/foo");75 });76 it("replaces blank urls with about:blank", () => {77 expect(sanitizeUrl("")).toBe("about:blank");78 });79 it("replaces null values with about:blank", () => {80 // eslint-disable-next-line @typescript-eslint/ban-ts-comment81 // @ts-ignore82 expect(sanitizeUrl(null)).toBe("about:blank");83 });84 it("replaces undefined values with about:blank", () => {85 expect(sanitizeUrl()).toBe("about:blank");86 });87 it("removes whitespace from urls", () => {88 expect(89 sanitizeUrl(90 " http://example.com/path/to:something ",91 ),92 ).toBe("http://example.com/path/to:something");93 });94 it("decodes html entities", () => {95 // all these decode to javascript:alert('xss');96 const attackVectors = [97 "javascript:alert('XSS')",98 "javascript:alert('XSS')",99 "javascript:alert('XSS')",100 "jav	ascript:alert('XSS');",101 "  javascript:alert('XSS');",102 ];103 attackVectors.forEach((vector) => {104 expect(sanitizeUrl(vector)).toBe("about:blank");105 });106 // https://example.com/javascript:alert('XSS')107 // since the javascript is the url path, and not the protocol,108 // this url is technically sanitized109 expect(110 sanitizeUrl(111 "https://example.com/javascript:alert('XSS')",112 ),113 ).toBe("https://example.com/javascript:alert('XSS')");114 });115 describe("invalid protocols", () => {116 describe.each(["javascript", "data", "vbscript"])(117 "%s",118 (protocol) => {119 it(`replaces ${protocol} urls with about:blank`, () => {120 expect(121 sanitizeUrl(122 `${protocol}:alert(document.domain)`,123 ),124 ).toBe("about:blank");125 });126 it(`allows ${protocol} urls that start with a letter prefix`, () => {127 expect(128 sanitizeUrl(129 `not_${protocol}:alert(document.domain)`,130 ),131 ).toBe(`not_${protocol}:alert(document.domain)`);132 });133 it(`disallows ${protocol} urls that start with non-\w characters as a suffix for the protocol`, () => {134 expect(135 sanitizeUrl(136 `&!*${protocol}:alert(document.domain)`,137 ),138 ).toBe("about:blank");139 });140 it(`disregards capitalization for ${protocol} urls`, () => {141 // upper case every other letter in protocol name142 const mixedCapitalizationProtocol = protocol143 .split("")144 .map((character, index) => {145 if (index % 2 === 0) {146 return character.toUpperCase();147 }148 return character;149 })150 .join("");151 expect(152 sanitizeUrl(153 `${mixedCapitalizationProtocol}:alert(document.domain)`,154 ),155 ).toBe("about:blank");156 });157 it(`ignores invisible ctrl characters in ${protocol} urls`, () => {158 const protocolWithControlCharacters = protocol159 .split("")160 .map((character, index) => {161 if (index === 1) {162 return character + "%EF%BB%BF%EF%BB%BF";163 } else if (index === 2) {164 return character + "%e2%80%8b";165 }166 return character;167 })168 .join("");169 expect(170 sanitizeUrl(171 decodeURIComponent(172 `${protocolWithControlCharacters}:alert(document.domain)`,173 ),174 ),175 ).toBe("about:blank");176 });177 it(`replaces ${protocol} urls with about:blank when url begins with %20`, () => {178 expect(179 sanitizeUrl(180 decodeURIComponent(181 `%20%20%20%20${protocol}:alert(document.domain)`,182 ),183 ),184 ).toBe("about:blank");185 });186 it(`replaces ${protocol} urls with about:blank when ${protocol} url begins with spaces`, () => {187 expect(188 sanitizeUrl(189 ` ${protocol}:alert(document.domain)`,190 ),191 ).toBe("about:blank");192 });193 it(`does not replace ${protocol}: if it is not in the scheme of the URL`, () => {194 expect(195 sanitizeUrl(196 `http://example.com#${protocol}:foo`,197 ),198 ).toBe(`http://example.com#${protocol}:foo`);199 });200 },201 );202 });...
utils.spec.ts
Source:utils.spec.ts
1import { sanitizeUrl } from "./utils";2describe('utils.sanitizeUrl', () => {3 it('URL should be sanitized', () => {4 expect(sanitizeUrl("http://localhost/path/to/file")).toBe("http://localhost/path/to/file");5 expect(sanitizeUrl("https://localhost/path/to/file")).toBe("https://localhost/path/to/file");6 expect(sanitizeUrl("ftp://localhost/path/to/file")).toBe("ftp://localhost/path/to/file");7 expect(sanitizeUrl("ftps://localhost/path/to/file")).toBe("ftps://localhost/path/to/file");8 expect(sanitizeUrl("javascript://localhost/path/to/file")).toBe("#");9 expect(sanitizeUrl("jAvasCrIPT://localhost/path/to/file")).toBe("#");10 expect(sanitizeUrl(null)).toBe("#");11 expect(sanitizeUrl("")).toBe("#");12 });13 it("replaces javascript urls with #", () => {14 expect(sanitizeUrl("javascript:alert(document.domain)")).toBe(15 "#"16 );17 });18 it("disregards capitalization for JavaScript urls", () => {19 expect(sanitizeUrl("jAvasCrIPT:alert(document.domain)")).toBe(20 "#"21 );22 });23 it("ignores ctrl characters in javascript urls", () => {24 expect(25 sanitizeUrl(decodeURIComponent("JaVaScRiP%0at:alert(document.domain)"))26 ).toBe("#");27 });28 it("replaces javascript urls with # when javascript url begins with %20", () => {29 expect(sanitizeUrl("%20%20%20%20javascript:alert(document.domain)")).toBe(30 "#"31 );32 });33 it("replaces javascript urls with # when javascript url begins with s", () => {34 expect(sanitizeUrl(" javascript:alert(document.domain)")).toBe(35 "#"36 );37 });38 it("does not replace javascript: if it is not in the scheme of the URL", () => {39 expect(sanitizeUrl("http://example.com#myjavascript:foo")).toBe(40 "http://example.com#myjavascript:foo"41 );42 });43 it("replaces data urls with #", () => {44 expect(45 sanitizeUrl(46 "data:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"47 )48 ).toBe("#");49 });50 it("replaces data urls with # when data url begins with %20", () => {51 expect(52 sanitizeUrl(53 "%20%20%20%20data:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"54 )55 ).toBe("#");56 });57 it("replaces data urls with # when data url begins with s", () => {58 expect(59 sanitizeUrl(60 " data:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"61 )62 ).toBe("#");63 });64 it("disregards capitalization for data urls", () => {65 expect(66 sanitizeUrl(67 "dAtA:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"68 )69 ).toBe("#");70 });71 it("ignores ctrl characters in data urls", () => {72 expect(73 sanitizeUrl(74 decodeURIComponent(75 "dat%0aa:text/html;base64,PH%3Cscript%3Ealert(document.domain)%3C/script%3E"76 )77 )78 ).toBe("#");79 });80 it("replaces VBscript urls with #", () => {81 expect(sanitizeUrl("vbscript:msgbox('XSS')")).toBe("#");82 });83 it("disregards capitalization for VBscript urls", () => {84 expect(sanitizeUrl("vbScrIpT:mSGBOX('XSS')")).toBe("#");85 });86 it("ignores ctrl characters in VBscript urls", () => {87 expect(sanitizeUrl(decodeURIComponent("VbScRiP%0at:msgbox('XSS')"))).toBe(88 "#"89 );90 });91 it("replaces VBscript urls with # when VBscript url begins with %20", () => {92 expect(sanitizeUrl("%20%20%20%20vbscript:msgbox('XSS')")).toBe(93 "#"94 );95 });96 it("replaces VBScript urls with # when VBscript url begins with s", () => {97 expect(sanitizeUrl(" vbscript:msgbox('XSS')")).toBe("#");98 });99 it("does not replace VBscript: if it is not in the scheme of the URL", () => {100 expect(sanitizeUrl("http://example.com#whatisvbscript:foo")).toBe(101 "http://example.com#whatisvbscript:foo"102 );103 });104 it("does not alter http URLs", () => {105 expect(sanitizeUrl("http://example.com/path/to:something")).toBe(106 "http://example.com/path/to:something"107 );108 });109 it("does not alter http URLs with ports", () => {110 expect(sanitizeUrl("http://example.com:4567/path/to:something")).toBe(111 "http://example.com:4567/path/to:something"112 );113 });114 it("does not alter https URLs", () => {115 expect(sanitizeUrl("https://example.com")).toBe("https://example.com");116 });117 it("does not alter https URLs with ports", () => {118 expect(sanitizeUrl("https://example.com:4567/path/to:something")).toBe(119 "https://example.com:4567/path/to:something"120 );121 });122 it("does not alter relative-path reference URLs", () => {123 expect(sanitizeUrl("./path/to/my.json")).toBe("./path/to/my.json");124 });125 it("does not alter absolute-path reference URLs", () => {126 expect(sanitizeUrl("/path/to/my.json")).toBe("/path/to/my.json");127 });128 it("does not alter protocol-less network-path URLs", () => {129 expect(sanitizeUrl("//google.com/robots.txt")).toBe(130 "//google.com/robots.txt"131 );132 });133 it("does not alter protocol-less URLs", () => {134 expect(sanitizeUrl("www.example.com")).toBe("www.example.com");135 });136 it("does not alter deep-link urls", () => {137 expect(sanitizeUrl("com.braintreepayments.demo://example")).toBe(138 "com.braintreepayments.demo://example"139 );140 });141 it("does not alter mailto urls", () => {142 expect(sanitizeUrl("mailto:test@example.com?subject=hello+world")).toBe(143 "mailto:test@example.com?subject=hello+world"144 );145 });146 it("does not alter urls with accented characters", () => {147 expect(sanitizeUrl("www.example.com/with-áccêntš")).toBe(148 "www.example.com/with-áccêntš"149 );150 });151 it("replaces blank urls with #", () => {152 expect(sanitizeUrl("")).toBe("#");153 });154 it("replaces null values with #", () => {155 expect(sanitizeUrl(null)).toBe("#");156 });157 it("replaces undefined values with #", () => {158 expect(sanitizeUrl()).toBe("#");159 });160 it("removes whitespace from urls", () => {161 expect(sanitizeUrl(" http://example.com/path/to:something ")).toBe(162 "http://example.com/path/to:something"163 );164 });...
info.jsx
Source:info.jsx
1import React from "react"2import PropTypes from "prop-types"3import ImPropTypes from "react-immutable-proptypes"4import { sanitizeUrl } from "core/utils"5import { buildUrl } from "core/utils/url"6export class InfoBasePath extends React.Component {7 static propTypes = {8 host: PropTypes.string,9 basePath: PropTypes.string10 }11 render() {12 let { host, basePath } = this.props13 return (14 <pre className="base-url">15 [ Base URL: {host}{basePath} ]16 </pre>17 )18 }19}20class Contact extends React.Component {21 static propTypes = {22 data: PropTypes.object,23 getComponent: PropTypes.func.isRequired,24 specSelectors: PropTypes.object.isRequired,25 selectedServer: PropTypes.string,26 url: PropTypes.string.isRequired,27 }28 render(){29 let { data, getComponent, selectedServer, url: specUrl} = this.props30 let name = data.get("name") || "the developer"31 let url = buildUrl(data.get("url"), specUrl, {selectedServer})32 let email = data.get("email")33 const Link = getComponent("Link")34 return (35 <div className="info__contact">36 { url && <div><Link href={ sanitizeUrl(url) } target="_blank">{ name } - Website</Link></div> }37 { email &&38 <Link href={sanitizeUrl(`mailto:${email}`)}>39 { url ? `Send email to ${name}` : `Contact ${name}`}40 </Link>41 }42 </div>43 )44 }45}46class License extends React.Component {47 static propTypes = {48 license: PropTypes.object,49 getComponent: PropTypes.func.isRequired,50 specSelectors: PropTypes.object.isRequired,51 selectedServer: PropTypes.string,52 url: PropTypes.string.isRequired,53 }54 render(){55 let { license, getComponent, selectedServer, url: specUrl } = this.props56 const Link = getComponent("Link")57 let name = license.get("name") || "License" 58 let url = buildUrl(license.get("url"), specUrl, {selectedServer})59 return (60 <div className="info__license">61 {62 url ? <Link target="_blank" href={ sanitizeUrl(url) }>{ name }</Link>63 : <span>{ name }</span>64 }65 </div>66 )67 }68}69export class InfoUrl extends React.PureComponent {70 static propTypes = {71 url: PropTypes.string.isRequired,72 getComponent: PropTypes.func.isRequired73 }74 render() {75 const { url, getComponent } = this.props76 const Link = getComponent("Link")77 return <Link target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url }</span></Link>78 }79}80export default class Info extends React.Component {81 static propTypes = {82 info: PropTypes.object,83 url: PropTypes.string,84 host: PropTypes.string,85 basePath: PropTypes.string,86 externalDocs: ImPropTypes.map,87 getComponent: PropTypes.func.isRequired,88 oas3selectors: PropTypes.func,89 selectedServer: PropTypes.string,90 }91 render() {92 let { info, url, host, basePath, getComponent, externalDocs, selectedServer, url: specUrl } = this.props93 let version = info.get("version")94 let description = info.get("description")95 let title = info.get("title")96 let termsOfServiceUrl = buildUrl(info.get("termsOfService"), specUrl, {selectedServer})97 let contact = info.get("contact")98 let license = info.get("license")99 let rawExternalDocsUrl = externalDocs && externalDocs.get("url")100 let externalDocsUrl = buildUrl(rawExternalDocsUrl, specUrl, {selectedServer})101 let externalDocsDescription = externalDocs && externalDocs.get("description")102 const Markdown = getComponent("Markdown", true)103 const Link = getComponent("Link")104 const VersionStamp = getComponent("VersionStamp")105 const InfoUrl = getComponent("InfoUrl")106 const InfoBasePath = getComponent("InfoBasePath")107 return (108 <div className="info">109 <hgroup className="main">110 <h2 className="title" >{ title }111 { version && <VersionStamp version={version}></VersionStamp> }112 </h2>113 { host || basePath ? <InfoBasePath host={ host } basePath={ basePath } /> : null }114 { url && <InfoUrl getComponent={getComponent} url={url} /> }115 </hgroup>116 <div className="description">117 <Markdown source={ description } />118 </div>119 {120 termsOfServiceUrl && <div className="info__tos">121 <Link target="_blank" href={ sanitizeUrl(termsOfServiceUrl) }>Terms of service</Link>122 </div>123 }124 {contact && contact.size ? <Contact getComponent={getComponent} data={ contact } selectedServer={selectedServer} url={url} /> : null }125 {license && license.size ? <License getComponent={getComponent} license={ license } selectedServer={selectedServer} url={url}/> : null }126 { externalDocsUrl ?127 <Link className="info__extdocs" target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</Link>128 : null }129 </div>130 )131 }132}133Info.propTypes = {134 title: PropTypes.any,135 description: PropTypes.any,136 version: PropTypes.any,137 url: PropTypes.string...
utils.test.js
Source:utils.test.js
1const utils = require('../helpers/utils');2describe('keyExists', () => {3 const obj = {4 key: 'value',5 anotherKey: 'another value',6 };7 it('should return false if key don\'t exist in object', () => {8 expect(utils.keyExists(obj, 'notExistedKey')).toBeFalsy();9 });10 it('should return true if key exist in object', () => {11 expect(utils.keyExists(obj, 'key')).toBeTruthy();12 expect(utils.keyExists(obj, 'anotherKey')).toBeTruthy();13 });14});15const checkForSameInputAndOutput = (inputs) => {16 inputs.forEach((input) => {17 expect(utils.sanitizeUrl(input)).toBe(input);18 });19};20describe('sanitizeUrl', () => {21 const standardGithubURL = 'https://www.github.com';22 const standardGithubURLWithPath = 'https://www.github.com/Marvin9';23 const standardGithubURLWithQuery = 'https://www.github.com/Marvin9?tab=repositories';24 it('should return empty string if url is invalid', () => {25 expect(utils.sanitizeUrl('invalidurl')).toBe('');26 });27 it('should return correct string for url containing -> protocol + subdomain + domain', () => {28 checkForSameInputAndOutput([29 standardGithubURL,30 standardGithubURLWithPath,31 standardGithubURLWithQuery,32 ]);33 });34 it('should return correct string (with subdomain as "www") for url containing -> protocol + domain', () => {35 const url = 'https://github.com';36 const urlWithPath = 'https://github.com/Marvin9';37 const urlWithQuery = 'https://github.com/Marvin9?tab=repositories';38 expect(utils.sanitizeUrl(url)).toBe(standardGithubURL);39 expect(utils.sanitizeUrl(urlWithPath)).toBe(standardGithubURLWithPath);40 expect(utils.sanitizeUrl(urlWithQuery)).toBe(standardGithubURLWithQuery);41 });42 it('should return correct string (with protocol as "https") for url containing -> subdomain + domain', () => {43 const url = 'www.github.com';44 expect(utils.sanitizeUrl(url)).toBe(standardGithubURL);45 });46 it('should return correct string (with protocol as "https" & subdomain as "www") for url containing -> domain', () => {47 const url = 'github.com';48 expect(utils.sanitizeUrl(url)).toBe(standardGithubURL);49 });...
index.test.js
Source:index.test.js
1/*2 * Copyright (C) 2019 - present Instructure, Inc.3 *4 * This file is part of Canvas.5 *6 * Canvas is free software: you can redistribute it and/or modify it under7 * the terms of the GNU Affero General Public License as published by the Free8 * Software Foundation, version 3 of the License.9 *10 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR12 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more13 * details.14 *15 * You should have received a copy of the GNU Affero General Public License along16 * with this program. If not, see <http://www.gnu.org/licenses/>.17 */18import sanitizeUrl from '../index'19it('replaces javascript: scheme urls with about:blank', () => {20 // eslint-disable-next-line no-script-url21 expect(sanitizeUrl('javascript:prompt(document.cookie);prompt(document.domain);')).toBe(22 'about:blank'23 )24})25it('is not fooled by obfuscating the scheme with newlines and stuff', () => {26 expect(sanitizeUrl('javascri\npt:prompt(document.cookie);prompt(document.domain);')).toBe(27 'about:blank'28 )29})30it('is not hoodwinked by mixed-case tomfoolery', () => {31 // eslint-disable-next-line no-script-url32 expect(sanitizeUrl('jaVascripT:prompt(document.cookie);prompt(document.domain);')).toBe(33 'about:blank'34 )35})36it('leaves normal non-javascript: http urls alone', () => {37 expect(sanitizeUrl('http://instructure.com')).toBe('http://instructure.com')38})39it('leaves normal non-javascript: https urls alone', () => {40 expect(sanitizeUrl('https://instructure.com')).toBe('https://instructure.com')41})42it('leaves schemeless absolute urls alone', () => {43 expect(sanitizeUrl('/index.html')).toBe('/index.html')44})45it('leaves relative urls alone', () => {46 expect(sanitizeUrl('lolcats.gif')).toBe('lolcats.gif')47})48it('replaces totally invalid urls with about:blank', () => {49 expect(sanitizeUrl('https://#')).toBe('about:blank')...
sanitizeUrl.test.js
Source:sanitizeUrl.test.js
1/*2 * Copyright (C) 2019 - present Instructure, Inc.3 *4 * This file is part of Canvas.5 *6 * Canvas is free software: you can redistribute it and/or modify it under7 * the terms of the GNU Affero General Public License as published by the Free8 * Software Foundation, version 3 of the License.9 *10 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR12 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more13 * details.14 *15 * You should have received a copy of the GNU Affero General Public License along16 * with this program. If not, see <http://www.gnu.org/licenses/>.17 */18import sanitizeUrl from '../sanitizeUrl'19it('replaces javascript: scheme urls with about:blank', () => {20 // eslint-disable-next-line no-script-url21 expect(sanitizeUrl('javascript:prompt(document.cookie);prompt(document.domain);')).toBe(22 'about:blank'23 )24})25it('is not fooled by obfuscating the scheme with newlines and stuff', () => {26 expect(sanitizeUrl('javascri\npt:prompt(document.cookie);prompt(document.domain);')).toBe(27 'about:blank'28 )29})30it('is not hoodwinked by mixed-case tomfoolery', () => {31 // eslint-disable-next-line no-script-url32 expect(sanitizeUrl('jaVascripT:prompt(document.cookie);prompt(document.domain);')).toBe(33 'about:blank'34 )35})36it('leaves normal non-javascript: http urls alone', () => {37 expect(sanitizeUrl('http://instructure.com')).toBe('http://instructure.com')38})39it('leaves normal non-javascript: https urls alone', () => {40 expect(sanitizeUrl('https://instructure.com')).toBe('https://instructure.com')41})42it('leaves schemeless absolute urls alone', () => {43 expect(sanitizeUrl('/index.html')).toBe('/index.html')44})45it('leaves relative urls alone', () => {46 expect(sanitizeUrl('lolcats.gif')).toBe('lolcats.gif')...
FlipkartLinks.js
Source:FlipkartLinks.js
2const url = require('url');3const sellerSchema = require('./_sellerLinksSchema');4mongoose.Promise = global.Promise;5const flipkartSchema = sellerSchema;6function sanitizeURL(next) {7 const { host, pathname, query, protocol } = url.parse(this.url, true);8 const pid = query.pid ? `?pid=${query.pid}` : '';9 let updatedPathname = pathname;;10 if (pathname.indexOf('/dl') !== 0) {11 pathname = `/dl${pathname}`;12 }13 let updatedHost = host.replace('www.flipkart.com', 'dl.flipkart.com');14 this.url = `${protocol}//${updatedHost}${updatedPathname}${pid}`;15 next();16}17flipkartSchema.pre('save', sanitizeURL);18flipkartSchema.pre('find', sanitizeURL);19flipkartSchema.pre('findOne', sanitizeURL);20module.exports = {...
Using AI Code Generation
1const { sanitizeURL } = require('playwright/lib/utils/utils');2const { chromium } = require('playwright');3(async () => {4const browser = await chromium.launch();5const context = await browser.newContext();6await context.setViewportSize({ width: 1280, height: 720 });7await context.close();8await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12const browser = await chromium.launch();13const context = await browser.newContext();14const page = await context.newPage();15const messages = await page.consoleMessages();16console.log(messages);17await context.close();18await browser.close();19})();
Using AI Code Generation
1const { sanitizeURL } = require('playwright/lib/utils/utils');2const { sanitizeURL } = require('playwright/lib/utils/utils');3const { sanitizeURL } = require('playwright/lib/utils/utils');4const { sanitizeURL } = require('playwright/lib/utils/utils');5const { sanitizeURL } = require('playwright/lib/utils/utils');6const { sanitizeURL } = require('playwright/lib/utils/utils');7const { sanitizeURL } = require('playwright/lib/utils/utils');8const { sanitizeURL } = require('playwright/lib/utils/utils');9const { sanitizeURL } = require('playwright/lib/utils/utils');10const { sanitizeURL } = require('playwright/lib
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!